ChaptersSettingsSheet: Single source of truth and use new manga class (#7342)
Currently breaks initial settings state until the source of truth is properly updated.
This commit is contained in:
parent
e6a9d0b090
commit
005b9b595c
@ -1,8 +1,10 @@
|
||||
package eu.kanade.domain.manga.model
|
||||
|
||||
import eu.kanade.tachiyomi.data.cache.CoverCache
|
||||
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
|
||||
@ -45,15 +47,99 @@ 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
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@ -66,6 +152,7 @@ fun Manga.toDbManga(): DbManga = DbManga.create(url, title, 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(
|
||||
|
@ -305,11 +305,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)
|
||||
|
||||
@ -873,6 +869,7 @@ class MangaController :
|
||||
}
|
||||
|
||||
updateFabVisibility()
|
||||
updateFilterIconState()
|
||||
}
|
||||
|
||||
private fun fetchChaptersFromSource(manualFetch: Boolean = false) {
|
||||
|
@ -6,35 +6,51 @@ import android.util.AttributeSet
|
||||
import android.view.View
|
||||
import androidx.core.view.isVisible
|
||||
import com.bluelinelabs.conductor.Router
|
||||
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.view.popupMenu
|
||||
import eu.kanade.tachiyomi.widget.ExtendedNavigationView
|
||||
import eu.kanade.tachiyomi.widget.ExtendedNavigationView.Item.TriStateGroup.State
|
||||
import eu.kanade.tachiyomi.widget.sheet.TabbedBottomSheetDialog
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.MainScope
|
||||
import kotlinx.coroutines.cancel
|
||||
|
||||
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,
|
||||
@ -47,6 +63,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,
|
||||
@ -79,6 +99,10 @@ class ChaptersSettingsSheet(
|
||||
return filterGroup.items.any { it.state != State.IGNORE.value }
|
||||
}
|
||||
|
||||
override fun updateView() {
|
||||
filterGroup.updateModels()
|
||||
}
|
||||
|
||||
inner class FilterGroup : Group {
|
||||
|
||||
private val downloaded = Item.TriStateGroup(R.string.action_filter_downloaded, this)
|
||||
@ -90,14 +114,20 @@ 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
|
||||
}
|
||||
|
||||
fun updateModels() {
|
||||
initModels()
|
||||
adapter.notifyItemRangeChanged(0, 3)
|
||||
}
|
||||
|
||||
override fun onItemClicked(item: Item) {
|
||||
@ -108,7 +138,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)
|
||||
@ -116,8 +145,9 @@ class ChaptersSettingsSheet(
|
||||
else -> {}
|
||||
}
|
||||
|
||||
initModels()
|
||||
adapter.notifyItemChanged(items.indexOf(item), item)
|
||||
// TODO: Remove
|
||||
updateManga()
|
||||
updateView()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -128,8 +158,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 {
|
||||
@ -143,8 +179,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
|
||||
@ -158,29 +195,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()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -191,8 +222,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 {
|
||||
@ -205,25 +242,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()
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -246,6 +287,9 @@ class ChaptersSettingsSheet(
|
||||
addView(recycler)
|
||||
}
|
||||
|
||||
open fun updateView() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Adapter of the recycler view.
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user