ChaptersSettingsSheet: Single source of truth and use new manga class (#7342)

Currently breaks initial settings state until the source of truth is
properly updated.

(cherry picked from commit 005b9b595cfe41484eea94998d2f3c9918759a94)

# Conflicts:
#	app/src/main/java/eu/kanade/domain/manga/model/Manga.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaController.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersSettingsSheet.kt
This commit is contained in:
Ivan Iskandar 2022-06-19 23:29:49 +07:00 committed by Jobobby04
parent 3f94fd8e6e
commit 29f992fe33
3 changed files with 183 additions and 51 deletions

View File

@ -2,8 +2,10 @@ package eu.kanade.domain.manga.model
import eu.kanade.tachiyomi.data.cache.CoverCache
import eu.kanade.tachiyomi.data.library.CustomMangaManager
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.source.LocalSource
import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.widget.ExtendedNavigationView
import tachiyomi.source.model.MangaInfo
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
@ -76,15 +78,85 @@ data class Manga(
}
}
companion object {
val displayMode: Long
get() = chapterFlags and CHAPTER_DISPLAY_MASK
val unreadFilterRaw: Long
get() = chapterFlags and CHAPTER_UNREAD_MASK
val downloadedFilterRaw: Long
get() = chapterFlags and CHAPTER_DOWNLOADED_MASK
val bookmarkedFilterRaw: Long
get() = chapterFlags and CHAPTER_BOOKMARKED_MASK
val unreadFilter: TriStateFilter
get() = when (unreadFilterRaw) {
CHAPTER_SHOW_UNREAD -> TriStateFilter.ENABLED_IS
CHAPTER_SHOW_READ -> TriStateFilter.ENABLED_NOT
else -> TriStateFilter.DISABLED
}
val downloadedFilter: TriStateFilter
get() {
if (forceDownloaded()) return TriStateFilter.ENABLED_IS
return when (downloadedFilterRaw) {
CHAPTER_SHOW_DOWNLOADED -> TriStateFilter.ENABLED_IS
CHAPTER_SHOW_NOT_DOWNLOADED -> TriStateFilter.ENABLED_NOT
else -> TriStateFilter.DISABLED
}
}
val bookmarkedFilter: TriStateFilter
get() = when (bookmarkedFilterRaw) {
CHAPTER_SHOW_BOOKMARKED -> TriStateFilter.ENABLED_IS
CHAPTER_SHOW_NOT_BOOKMARKED -> TriStateFilter.ENABLED_NOT
else -> TriStateFilter.DISABLED
}
fun chaptersFiltered(): Boolean {
return unreadFilter != TriStateFilter.DISABLED ||
downloadedFilter != TriStateFilter.DISABLED ||
bookmarkedFilter != TriStateFilter.DISABLED
}
fun forceDownloaded(): Boolean {
return favorite && Injekt.get<PreferencesHelper>().downloadedOnly().get()
}
fun sortDescending(): Boolean {
return chapterFlags and CHAPTER_SORT_DIR_MASK == CHAPTER_SORTING_DESC
}
companion object {
// Generic filter that does not filter anything
const val SHOW_ALL = 0x00000000L
const val CHAPTER_SORT_DESC = 0x00000000L
const val CHAPTER_SORT_ASC = 0x00000001L
const val CHAPTER_SORT_DIR_MASK = 0x00000001L
const val CHAPTER_SHOW_UNREAD = 0x00000002L
const val CHAPTER_SHOW_READ = 0x00000004L
const val CHAPTER_UNREAD_MASK = 0x00000006L
const val CHAPTER_SHOW_DOWNLOADED = 0x00000008L
const val CHAPTER_SHOW_NOT_DOWNLOADED = 0x00000010L
const val CHAPTER_DOWNLOADED_MASK = 0x00000018L
const val CHAPTER_SHOW_BOOKMARKED = 0x00000020L
const val CHAPTER_SHOW_NOT_BOOKMARKED = 0x00000040L
const val CHAPTER_BOOKMARKED_MASK = 0x00000060L
const val CHAPTER_SORTING_SOURCE = 0x00000000L
const val CHAPTER_SORTING_NUMBER = 0x00000100L
const val CHAPTER_SORTING_UPLOAD_DATE = 0x00000200L
const val CHAPTER_SORTING_MASK = 0x00000300L
const val CHAPTER_SORTING_DESC = 0x00000000L
const val CHAPTER_DISPLAY_NAME = 0x00000000L
const val CHAPTER_DISPLAY_NUMBER = 0x00100000L
const val CHAPTER_DISPLAY_MASK = 0x00100000L
// SY -->
private val customMangaManager: CustomMangaManager by injectLazy()
@ -92,6 +164,20 @@ data class Manga(
}
}
enum class TriStateFilter {
DISABLED, // Disable filter
ENABLED_IS, // Enabled with "is" filter
ENABLED_NOT, // Enabled with "not" filter
}
fun TriStateFilter.toTriStateGroupState(): ExtendedNavigationView.Item.TriStateGroup.State {
return when (this) {
TriStateFilter.DISABLED -> ExtendedNavigationView.Item.TriStateGroup.State.IGNORE
TriStateFilter.ENABLED_IS -> ExtendedNavigationView.Item.TriStateGroup.State.INCLUDE
TriStateFilter.ENABLED_NOT -> ExtendedNavigationView.Item.TriStateGroup.State.EXCLUDE
}
}
// TODO: Remove when all deps are migrated
fun Manga.toDbManga(): DbManga = DbManga.create(url, ogTitle, source).also {
it.id = id
@ -101,6 +187,7 @@ fun Manga.toDbManga(): DbManga = DbManga.create(url, ogTitle, source).also {
it.viewer_flags = viewerFlags.toInt()
it.chapter_flags = chapterFlags.toInt()
it.cover_last_modified = coverLastModified
it.thumbnail_url = thumbnailUrl
}
fun Manga.toMangaInfo(): MangaInfo = MangaInfo(

View File

@ -378,11 +378,7 @@ class MangaController :
}
.launchIn(viewScope)
settingsSheet = ChaptersSettingsSheet(router, presenter) { group ->
if (group is ChaptersSettingsSheet.Filter.FilterGroup) {
updateFilterIconState()
}
}
settingsSheet = ChaptersSettingsSheet(router, presenter)
trackSheet = TrackSheet(this, manga!!, (activity as MainActivity).supportFragmentManager)
@ -1092,6 +1088,7 @@ class MangaController :
}
updateFabVisibility()
updateFilterIconState()
settingsSheet?.filters?.updateScanlatorFilter()
}

View File

@ -7,8 +7,10 @@ import android.view.View
import androidx.core.view.isVisible
import com.bluelinelabs.conductor.Router
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import eu.kanade.domain.manga.model.Manga
import eu.kanade.domain.manga.model.toTriStateGroupState
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.database.models.toDomainManga
import eu.kanade.tachiyomi.ui.manga.MangaPresenter
import eu.kanade.tachiyomi.util.lang.launchIO
import eu.kanade.tachiyomi.util.lang.withUIContext
@ -17,29 +19,43 @@ import eu.kanade.tachiyomi.widget.ExtendedNavigationView
import eu.kanade.tachiyomi.widget.ExtendedNavigationView.Item.TriStateGroup.State
import eu.kanade.tachiyomi.widget.sheet.TabbedBottomSheetDialog
import exh.md.utils.MdUtil
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.cancel
import kotlinx.coroutines.supervisorScope
class ChaptersSettingsSheet(
private val router: Router,
private val presenter: MangaPresenter,
private val onGroupClickListener: (ExtendedNavigationView.Group) -> Unit,
) : TabbedBottomSheetDialog(router.activity!!) {
val filters = Filter(router.activity!!)
private val sort = Sort(router.activity!!)
private val display = Display(router.activity!!)
private lateinit var scope: CoroutineScope
private var manga: Manga? = null
val filters = Filter(context)
private val sort = Sort(context)
private val display = Display(context)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
filters.onGroupClicked = onGroupClickListener
sort.onGroupClicked = onGroupClickListener
display.onGroupClicked = onGroupClickListener
binding.menu.isVisible = true
binding.menu.setOnClickListener { it.post { showPopupMenu(it) } }
}
override fun onAttachedToWindow() {
super.onAttachedToWindow()
scope = MainScope()
// TODO: Listen to changes
updateManga()
}
override fun onDetachedFromWindow() {
super.onDetachedFromWindow()
scope.cancel()
}
override fun getTabViews(): List<View> = listOf(
filters,
sort,
@ -52,6 +68,10 @@ class ChaptersSettingsSheet(
R.string.action_display,
)
private fun updateManga() {
manga = presenter.manga.toDomainManga()
}
private fun showPopupMenu(view: View) {
view.popupMenu(
menuRes = R.menu.default_chapter_filter,
@ -88,6 +108,10 @@ class ChaptersSettingsSheet(
filterGroup.updateScanlatorFilter()
}
override fun updateView() {
filterGroup.updateModels()
}
inner class FilterGroup : Group {
private val downloaded = Item.TriStateGroup(R.string.action_filter_downloaded, this)
@ -101,20 +125,30 @@ class ChaptersSettingsSheet(
override val footer: Item? = null
override fun initModels() {
if (presenter.forceDownloaded()) {
val manga = manga ?: return
if (manga.forceDownloaded()) {
downloaded.state = State.INCLUDE.value
downloaded.enabled = false
} else {
downloaded.state = presenter.onlyDownloaded().value
downloaded.state = manga.downloadedFilter.toTriStateGroupState().value
}
unread.state = presenter.onlyUnread().value
bookmarked.state = presenter.onlyBookmarked().value
unread.state = manga.unreadFilter.toTriStateGroupState().value
bookmarked.state = manga.bookmarkedFilter.toTriStateGroupState().value
// SY -->
updateScanlatorFilter()
// SY <--
}
fun updateModels() {
initModels()
adapter.notifyItemRangeChanged(0, 3)
}
// SY -->
fun updateScanlatorFilter() {
scanlatorFilters.isVisible = presenter.allChapterScanlators.size > 1
}
// SY <--
override fun onItemClicked(item: Item) {
if (item is Item.DrawableSelection) {
@ -156,7 +190,6 @@ class ChaptersSettingsSheet(
State.EXCLUDE.value -> State.IGNORE
else -> throw Exception("Unknown State")
}
item.state = newState.value
when (item) {
downloaded -> presenter.setDownloadedFilter(newState)
unread -> presenter.setUnreadFilter(newState)
@ -164,8 +197,9 @@ class ChaptersSettingsSheet(
else -> {}
}
initModels()
adapter.notifyItemChanged(items.indexOf(item), item)
// TODO: Remove
updateManga()
updateView()
}
}
}
@ -176,8 +210,14 @@ class ChaptersSettingsSheet(
inner class Sort @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
Settings(context, attrs) {
private val group = SortGroup()
init {
setGroups(listOf(SortGroup()))
setGroups(listOf(group))
}
override fun updateView() {
group.updateModels()
}
inner class SortGroup : Group {
@ -191,8 +231,9 @@ class ChaptersSettingsSheet(
override val footer: Item? = null
override fun initModels() {
val sorting = presenter.manga.sorting
val order = if (presenter.manga.sortDescending()) {
val manga = manga ?: return
val sorting = manga.sorting
val order = if (manga.sortDescending()) {
Item.MultiSort.SORT_DESC
} else {
Item.MultiSort.SORT_ASC
@ -206,29 +247,23 @@ class ChaptersSettingsSheet(
if (sorting == Manga.CHAPTER_SORTING_UPLOAD_DATE) order else Item.MultiSort.SORT_NONE
}
override fun onItemClicked(item: Item) {
items.forEachIndexed { i, multiSort ->
multiSort.state = if (multiSort == item) {
when (item.state) {
Item.MultiSort.SORT_NONE -> Item.MultiSort.SORT_ASC
Item.MultiSort.SORT_ASC -> Item.MultiSort.SORT_DESC
Item.MultiSort.SORT_DESC -> Item.MultiSort.SORT_ASC
else -> throw Exception("Unknown state")
}
} else {
Item.MultiSort.SORT_NONE
}
adapter.notifyItemChanged(i, multiSort)
}
fun updateModels() {
initModels()
adapter.notifyItemRangeChanged(0, 3)
}
override fun onItemClicked(item: Item) {
when (item) {
source -> presenter.setSorting(Manga.CHAPTER_SORTING_SOURCE)
chapterNum -> presenter.setSorting(Manga.CHAPTER_SORTING_NUMBER)
uploadDate -> presenter.setSorting(Manga.CHAPTER_SORTING_UPLOAD_DATE)
source -> presenter.setSorting(Manga.CHAPTER_SORTING_SOURCE.toInt())
chapterNum -> presenter.setSorting(Manga.CHAPTER_SORTING_NUMBER.toInt())
uploadDate -> presenter.setSorting(Manga.CHAPTER_SORTING_UPLOAD_DATE.toInt())
else -> throw Exception("Unknown sorting")
}
// TODO: Remove
presenter.reverseSortOrder()
updateManga()
updateView()
}
}
}
@ -239,8 +274,14 @@ class ChaptersSettingsSheet(
inner class Display @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
Settings(context, attrs) {
private val group = DisplayGroup()
init {
setGroups(listOf(DisplayGroup()))
setGroups(listOf(group))
}
override fun updateView() {
group.updateModels()
}
inner class DisplayGroup : Group {
@ -253,25 +294,29 @@ class ChaptersSettingsSheet(
override val footer: Item? = null
override fun initModels() {
val mode = presenter.manga.displayMode
val mode = manga?.displayMode ?: return
displayTitle.checked = mode == Manga.CHAPTER_DISPLAY_NAME
displayChapterNum.checked = mode == Manga.CHAPTER_DISPLAY_NUMBER
}
fun updateModels() {
initModels()
adapter.notifyItemRangeChanged(0, 2)
}
override fun onItemClicked(item: Item) {
item as Item.Radio
if (item.checked) return
items.forEachIndexed { index, radio ->
radio.checked = item == radio
adapter.notifyItemChanged(index, radio)
}
when (item) {
displayTitle -> presenter.setDisplayMode(Manga.CHAPTER_DISPLAY_NAME)
displayChapterNum -> presenter.setDisplayMode(Manga.CHAPTER_DISPLAY_NUMBER)
displayTitle -> presenter.setDisplayMode(Manga.CHAPTER_DISPLAY_NAME.toInt())
displayChapterNum -> presenter.setDisplayMode(Manga.CHAPTER_DISPLAY_NUMBER.toInt())
else -> throw NotImplementedError("Unknown display mode")
}
// TODO: Remove
updateManga()
updateView()
}
}
}
@ -294,6 +339,9 @@ class ChaptersSettingsSheet(
addView(recycler)
}
open fun updateView() {
}
/**
* Adapter of the recycler view.
*/