mirror of
https://github.com/tachiyomiorg/tachiyomi.git
synced 2024-12-23 00:31:51 +01:00
Move chapter filter/sort/display settings into a sheet
This commit is contained in:
parent
d7a70b962b
commit
9278ca3f5e
@ -24,10 +24,6 @@ interface Manga : SManga {
|
||||
setFlags(order, SORT_MASK)
|
||||
}
|
||||
|
||||
private fun setFlags(flag: Int, mask: Int) {
|
||||
chapter_flags = chapter_flags and mask.inv() or (flag and mask)
|
||||
}
|
||||
|
||||
fun sortDescending(): Boolean {
|
||||
return chapter_flags and SORT_MASK == SORT_DESC
|
||||
}
|
||||
@ -36,6 +32,10 @@ interface Manga : SManga {
|
||||
return genre?.split(", ")?.map { it.trim() }
|
||||
}
|
||||
|
||||
private fun setFlags(flag: Int, mask: Int) {
|
||||
chapter_flags = chapter_flags and mask.inv() or (flag and mask)
|
||||
}
|
||||
|
||||
// Used to display the chapter's title one way or another
|
||||
var displayMode: Int
|
||||
get() = chapter_flags and DISPLAY_MASK
|
||||
|
@ -13,7 +13,6 @@ import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.appcompat.view.ActionMode
|
||||
import androidx.core.graphics.drawable.DrawableCompat
|
||||
import androidx.recyclerview.widget.ConcatAdapter
|
||||
import androidx.recyclerview.widget.DividerItemDecoration
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
@ -51,6 +50,7 @@ import eu.kanade.tachiyomi.ui.main.offsetAppbarHeight
|
||||
import eu.kanade.tachiyomi.ui.manga.chapter.ChapterHolder
|
||||
import eu.kanade.tachiyomi.ui.manga.chapter.ChapterItem
|
||||
import eu.kanade.tachiyomi.ui.manga.chapter.ChaptersAdapter
|
||||
import eu.kanade.tachiyomi.ui.manga.chapter.ChaptersSettingsSheet
|
||||
import eu.kanade.tachiyomi.ui.manga.chapter.DeleteChaptersDialog
|
||||
import eu.kanade.tachiyomi.ui.manga.chapter.DownloadCustomChaptersDialog
|
||||
import eu.kanade.tachiyomi.ui.manga.chapter.MangaChaptersHeaderAdapter
|
||||
@ -61,7 +61,6 @@ import eu.kanade.tachiyomi.ui.recent.history.HistoryController
|
||||
import eu.kanade.tachiyomi.ui.recent.updates.UpdatesController
|
||||
import eu.kanade.tachiyomi.ui.webview.WebViewActivity
|
||||
import eu.kanade.tachiyomi.util.hasCustomCover
|
||||
import eu.kanade.tachiyomi.util.system.getResourceColor
|
||||
import eu.kanade.tachiyomi.util.system.toast
|
||||
import eu.kanade.tachiyomi.util.view.getCoordinates
|
||||
import eu.kanade.tachiyomi.util.view.gone
|
||||
@ -124,6 +123,11 @@ class MangaController :
|
||||
private var chaptersHeaderAdapter: MangaChaptersHeaderAdapter? = null
|
||||
private var chaptersAdapter: ChaptersAdapter? = null
|
||||
|
||||
/**
|
||||
* Sheet containing filter/sort/display items.
|
||||
*/
|
||||
private var settingsSheet: ChaptersSettingsSheet? = null
|
||||
|
||||
private var actionFabScrollListener: RecyclerView.OnScrollListener? = null
|
||||
|
||||
/**
|
||||
@ -178,7 +182,7 @@ class MangaController :
|
||||
|
||||
// Init RecyclerView and adapter
|
||||
mangaInfoAdapter = MangaInfoHeaderAdapter(this, fromSource)
|
||||
chaptersHeaderAdapter = MangaChaptersHeaderAdapter()
|
||||
chaptersHeaderAdapter = MangaChaptersHeaderAdapter(this)
|
||||
chaptersAdapter = ChaptersAdapter(this, view.context)
|
||||
|
||||
binding.recycler.adapter = ConcatAdapter(mangaInfoAdapter, chaptersHeaderAdapter, chaptersAdapter)
|
||||
@ -205,6 +209,19 @@ class MangaController :
|
||||
.launchIn(scope)
|
||||
|
||||
binding.actionToolbar.offsetAppbarHeight(activity!!)
|
||||
|
||||
settingsSheet = ChaptersSettingsSheet(activity!!, presenter) { group ->
|
||||
if (group is ChaptersSettingsSheet.Filter.FilterGroup) {
|
||||
updateFilterIconState()
|
||||
chaptersAdapter?.notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
|
||||
updateFilterIconState()
|
||||
}
|
||||
|
||||
private fun updateFilterIconState() {
|
||||
chaptersHeaderAdapter?.setHasActiveFilters(settingsSheet?.filters?.hasActiveFilters() == true)
|
||||
}
|
||||
|
||||
override fun configureFab(fab: ExtendedFloatingActionButton) {
|
||||
@ -249,6 +266,7 @@ class MangaController :
|
||||
mangaInfoAdapter = null
|
||||
chaptersHeaderAdapter = null
|
||||
chaptersAdapter = null
|
||||
settingsSheet = null
|
||||
super.onDestroyView(view)
|
||||
}
|
||||
|
||||
@ -266,50 +284,10 @@ class MangaController :
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
||||
inflater.inflate(R.menu.chapters, menu)
|
||||
inflater.inflate(R.menu.manga, menu)
|
||||
}
|
||||
|
||||
override fun onPrepareOptionsMenu(menu: Menu) {
|
||||
// Initialize menu items.
|
||||
val menuFilterRead = menu.findItem(R.id.action_filter_read) ?: return
|
||||
val menuFilterUnread = menu.findItem(R.id.action_filter_unread)
|
||||
val menuFilterDownloaded = menu.findItem(R.id.action_filter_downloaded)
|
||||
val menuFilterBookmarked = menu.findItem(R.id.action_filter_bookmarked)
|
||||
val menuFilterEmpty = menu.findItem(R.id.action_filter_empty)
|
||||
|
||||
// Set correct checkbox values.
|
||||
menuFilterRead.isChecked = presenter.onlyRead()
|
||||
menuFilterUnread.isChecked = presenter.onlyUnread()
|
||||
menuFilterDownloaded.isChecked = presenter.onlyDownloaded()
|
||||
menuFilterDownloaded.isEnabled = !presenter.forceDownloaded()
|
||||
menuFilterBookmarked.isChecked = presenter.onlyBookmarked()
|
||||
|
||||
val filterSet = presenter.onlyRead() || presenter.onlyUnread() || presenter.onlyDownloaded() || presenter.onlyBookmarked()
|
||||
if (filterSet) {
|
||||
val filterColor = activity!!.getResourceColor(R.attr.colorFilterActive)
|
||||
DrawableCompat.setTint(menu.findItem(R.id.action_filter).icon, filterColor)
|
||||
}
|
||||
|
||||
// Only show remove filter option if there's a filter set.
|
||||
menuFilterEmpty.isVisible = filterSet
|
||||
|
||||
// Display mode submenu
|
||||
if (presenter.manga.displayMode == Manga.DISPLAY_NAME) {
|
||||
menu.findItem(R.id.display_title).isChecked = true
|
||||
} else {
|
||||
menu.findItem(R.id.display_chapter_number).isChecked = true
|
||||
}
|
||||
|
||||
// Sorting mode submenu
|
||||
val sortingItem = when (presenter.manga.sorting) {
|
||||
Manga.SORTING_SOURCE -> R.id.sort_by_source
|
||||
Manga.SORTING_NUMBER -> R.id.sort_by_number
|
||||
Manga.SORTING_UPLOAD_DATE -> R.id.sort_by_upload_date
|
||||
else -> throw NotImplementedError("Unimplemented sorting method")
|
||||
}
|
||||
menu.findItem(sortingItem).isChecked = true
|
||||
menu.findItem(R.id.action_sort_descending).isChecked = presenter.manga.sortDescending()
|
||||
|
||||
// Hide download options for local manga
|
||||
menu.findItem(R.id.download_group).isVisible = !isLocalSource
|
||||
|
||||
@ -321,61 +299,10 @@ class MangaController :
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
when (item.itemId) {
|
||||
R.id.display_title -> {
|
||||
item.isChecked = true
|
||||
setDisplayMode(Manga.DISPLAY_NAME)
|
||||
}
|
||||
R.id.display_chapter_number -> {
|
||||
item.isChecked = true
|
||||
setDisplayMode(Manga.DISPLAY_NUMBER)
|
||||
}
|
||||
|
||||
R.id.sort_by_source -> {
|
||||
item.isChecked = true
|
||||
presenter.setSorting(Manga.SORTING_SOURCE)
|
||||
}
|
||||
R.id.sort_by_number -> {
|
||||
item.isChecked = true
|
||||
presenter.setSorting(Manga.SORTING_NUMBER)
|
||||
}
|
||||
R.id.sort_by_upload_date -> {
|
||||
item.isChecked = true
|
||||
presenter.setSorting(Manga.SORTING_UPLOAD_DATE)
|
||||
}
|
||||
R.id.action_sort_descending -> {
|
||||
presenter.reverseSortOrder()
|
||||
activity?.invalidateOptionsMenu()
|
||||
}
|
||||
|
||||
R.id.download_next, R.id.download_next_5, R.id.download_next_10,
|
||||
R.id.download_custom, R.id.download_unread, R.id.download_all
|
||||
-> downloadChapters(item.itemId)
|
||||
|
||||
R.id.action_filter_unread -> {
|
||||
item.isChecked = !item.isChecked
|
||||
presenter.setUnreadFilter(item.isChecked)
|
||||
activity?.invalidateOptionsMenu()
|
||||
}
|
||||
R.id.action_filter_read -> {
|
||||
item.isChecked = !item.isChecked
|
||||
presenter.setReadFilter(item.isChecked)
|
||||
activity?.invalidateOptionsMenu()
|
||||
}
|
||||
R.id.action_filter_downloaded -> {
|
||||
item.isChecked = !item.isChecked
|
||||
presenter.setDownloadedFilter(item.isChecked)
|
||||
activity?.invalidateOptionsMenu()
|
||||
}
|
||||
R.id.action_filter_bookmarked -> {
|
||||
item.isChecked = !item.isChecked
|
||||
presenter.setBookmarkedFilter(item.isChecked)
|
||||
activity?.invalidateOptionsMenu()
|
||||
}
|
||||
R.id.action_filter_empty -> {
|
||||
presenter.removeFilters()
|
||||
activity?.invalidateOptionsMenu()
|
||||
}
|
||||
|
||||
R.id.action_edit_categories -> onCategoriesClick()
|
||||
R.id.action_edit_cover -> handleChangeCover()
|
||||
R.id.action_migrate -> migrateManga()
|
||||
@ -756,6 +683,10 @@ class MangaController :
|
||||
chaptersAdapter?.notifyDataSetChanged()
|
||||
}
|
||||
|
||||
fun showSettingsSheet() {
|
||||
settingsSheet?.show()
|
||||
}
|
||||
|
||||
// SELECTIONS & ACTION MODE
|
||||
|
||||
private fun toggleSelection(position: Int) {
|
||||
@ -958,11 +889,6 @@ class MangaController :
|
||||
|
||||
// OVERFLOW MENU DIALOGS
|
||||
|
||||
private fun setDisplayMode(id: Int) {
|
||||
presenter.setDisplayMode(id)
|
||||
chaptersAdapter?.notifyDataSetChanged()
|
||||
}
|
||||
|
||||
private fun getUnreadChaptersSorted() = presenter.chapters
|
||||
.filter { !it.read && it.status == Download.NOT_DOWNLOADED }
|
||||
.distinctBy { it.name }
|
||||
|
@ -531,17 +531,6 @@ class MangaPresenter(
|
||||
refreshChapters()
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all filters and requests an UI update.
|
||||
*/
|
||||
fun removeFilters() {
|
||||
manga.readFilter = Manga.SHOW_ALL
|
||||
manga.downloadedFilter = Manga.SHOW_ALL
|
||||
manga.bookmarkedFilter = Manga.SHOW_ALL
|
||||
db.updateFlags(manga).executeAsBlocking()
|
||||
refreshChapters()
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the active display mode.
|
||||
* @param mode the mode to set.
|
||||
|
@ -0,0 +1,239 @@
|
||||
package eu.kanade.tachiyomi.ui.manga.chapter
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import android.view.View
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||
import eu.kanade.tachiyomi.ui.manga.MangaPresenter
|
||||
import eu.kanade.tachiyomi.widget.ExtendedNavigationView
|
||||
import eu.kanade.tachiyomi.widget.TabbedBottomSheetDialog
|
||||
|
||||
class ChaptersSettingsSheet(
|
||||
activity: Activity,
|
||||
private val presenter: MangaPresenter,
|
||||
onGroupClickListener: (ExtendedNavigationView.Group) -> Unit
|
||||
) : TabbedBottomSheetDialog(activity) {
|
||||
|
||||
val filters: Filter
|
||||
private val sort: Sort
|
||||
private val display: Display
|
||||
|
||||
init {
|
||||
filters = Filter(activity)
|
||||
filters.onGroupClicked = onGroupClickListener
|
||||
|
||||
sort = Sort(activity)
|
||||
sort.onGroupClicked = onGroupClickListener
|
||||
|
||||
display = Display(activity)
|
||||
display.onGroupClicked = onGroupClickListener
|
||||
}
|
||||
|
||||
override fun getTabViews(): List<View> = listOf(
|
||||
filters,
|
||||
sort,
|
||||
display
|
||||
)
|
||||
|
||||
override fun getTabTitles(): List<Int> = listOf(
|
||||
R.string.action_filter,
|
||||
R.string.action_sort,
|
||||
R.string.action_display
|
||||
)
|
||||
|
||||
/**
|
||||
* Filters group (unread, downloaded, ...).
|
||||
*/
|
||||
inner class Filter @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
|
||||
Settings(context, attrs) {
|
||||
|
||||
private val filterGroup = FilterGroup()
|
||||
|
||||
init {
|
||||
setGroups(listOf(filterGroup))
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if there's at least one filter from [FilterGroup] active.
|
||||
*/
|
||||
fun hasActiveFilters(): Boolean {
|
||||
return filterGroup.items.any { it.checked }
|
||||
}
|
||||
|
||||
inner class FilterGroup : Group {
|
||||
|
||||
private val read = Item.CheckboxGroup(R.string.action_filter_read, this)
|
||||
private val unread = Item.CheckboxGroup(R.string.action_filter_unread, this)
|
||||
private val downloaded = Item.CheckboxGroup(R.string.action_filter_downloaded, this)
|
||||
private val bookmarked = Item.CheckboxGroup(R.string.action_filter_bookmarked, this)
|
||||
|
||||
override val header = null
|
||||
override val items = listOf(read, unread, downloaded, bookmarked)
|
||||
override val footer = null
|
||||
|
||||
override fun initModels() {
|
||||
read.checked = presenter.onlyRead()
|
||||
unread.checked = presenter.onlyUnread()
|
||||
downloaded.checked = presenter.onlyDownloaded()
|
||||
downloaded.enabled = !presenter.forceDownloaded()
|
||||
bookmarked.checked = presenter.onlyBookmarked()
|
||||
}
|
||||
|
||||
override fun onItemClicked(item: Item) {
|
||||
item as Item.CheckboxGroup
|
||||
item.checked = !item.checked
|
||||
when (item) {
|
||||
read -> presenter.setReadFilter(item.checked)
|
||||
unread -> presenter.setUnreadFilter(item.checked)
|
||||
downloaded -> presenter.setDownloadedFilter(item.checked)
|
||||
bookmarked -> presenter.setBookmarkedFilter(item.checked)
|
||||
}
|
||||
|
||||
initModels()
|
||||
item.group.items.forEach { adapter.notifyItemChanged(it) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorting group (alphabetically, by last read, ...) and ascending or descending.
|
||||
*/
|
||||
inner class Sort @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
|
||||
Settings(context, attrs) {
|
||||
|
||||
init {
|
||||
setGroups(listOf(SortGroup()))
|
||||
}
|
||||
|
||||
inner class SortGroup : Group {
|
||||
|
||||
private val source = Item.MultiSort(R.string.sort_by_source, this)
|
||||
private val chapterNum = Item.MultiSort(R.string.sort_by_number, this)
|
||||
private val uploadDate = Item.MultiSort(R.string.sort_by_upload_date, this)
|
||||
|
||||
override val header = null
|
||||
override val items = listOf(source, uploadDate, chapterNum)
|
||||
override val footer = null
|
||||
|
||||
override fun initModels() {
|
||||
val sorting = presenter.manga.sorting
|
||||
val order = if (presenter.manga.sortDescending()) {
|
||||
Item.MultiSort.SORT_DESC
|
||||
} else {
|
||||
Item.MultiSort.SORT_ASC
|
||||
}
|
||||
|
||||
source.state =
|
||||
if (sorting == Manga.SORTING_SOURCE) order else Item.MultiSort.SORT_NONE
|
||||
chapterNum.state =
|
||||
if (sorting == Manga.SORTING_NUMBER) order else Item.MultiSort.SORT_NONE
|
||||
uploadDate.state =
|
||||
if (sorting == Manga.SORTING_UPLOAD_DATE) order else Item.MultiSort.SORT_NONE
|
||||
}
|
||||
|
||||
override fun onItemClicked(item: Item) {
|
||||
item as Item.MultiStateGroup
|
||||
val prevState = item.state
|
||||
|
||||
item.group.items.forEach {
|
||||
(it as Item.MultiStateGroup).state =
|
||||
Item.MultiSort.SORT_NONE
|
||||
}
|
||||
item.state = when (prevState) {
|
||||
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")
|
||||
}
|
||||
|
||||
when (item) {
|
||||
source -> presenter.setSorting(Manga.SORTING_SOURCE)
|
||||
chapterNum -> presenter.setSorting(Manga.SORTING_NUMBER)
|
||||
uploadDate -> presenter.setSorting(Manga.SORTING_UPLOAD_DATE)
|
||||
else -> throw Exception("Unknown sorting")
|
||||
}
|
||||
|
||||
presenter.reverseSortOrder()
|
||||
|
||||
item.group.items.forEach { adapter.notifyItemChanged(it) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Display group, to show the library as a list or a grid.
|
||||
*/
|
||||
inner class Display @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
|
||||
Settings(context, attrs) {
|
||||
|
||||
init {
|
||||
setGroups(listOf(DisplayGroup()))
|
||||
}
|
||||
|
||||
inner class DisplayGroup : Group {
|
||||
|
||||
private val displayTitle = Item.Radio(R.string.show_title, this)
|
||||
private val displayChapterNum = Item.Radio(R.string.show_chapter_number, this)
|
||||
|
||||
override val header = null
|
||||
override val items = listOf(displayTitle, displayChapterNum)
|
||||
override val footer = null
|
||||
|
||||
override fun initModels() {
|
||||
val mode = presenter.manga.displayMode
|
||||
displayTitle.checked = mode == Manga.DISPLAY_NAME
|
||||
displayChapterNum.checked = mode == Manga.DISPLAY_NUMBER
|
||||
}
|
||||
|
||||
override fun onItemClicked(item: Item) {
|
||||
item as Item.Radio
|
||||
if (item.checked) return
|
||||
|
||||
item.group.items.forEach { (it as Item.Radio).checked = false }
|
||||
item.checked = true
|
||||
|
||||
when (item) {
|
||||
displayTitle -> presenter.setDisplayMode(Manga.DISPLAY_NAME)
|
||||
displayChapterNum -> presenter.setDisplayMode(Manga.DISPLAY_NUMBER)
|
||||
else -> throw NotImplementedError("Unknown display mode")
|
||||
}
|
||||
|
||||
item.group.items.forEach { adapter.notifyItemChanged(it) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
open inner class Settings(context: Context, attrs: AttributeSet?) :
|
||||
ExtendedNavigationView(context, attrs) {
|
||||
|
||||
lateinit var adapter: Adapter
|
||||
|
||||
/**
|
||||
* Click listener to notify the parent fragment when an item from a group is clicked.
|
||||
*/
|
||||
var onGroupClicked: (Group) -> Unit = {}
|
||||
|
||||
fun setGroups(groups: List<Group>) {
|
||||
adapter = Adapter(groups.map { it.createItems() }.flatten())
|
||||
recycler.adapter = adapter
|
||||
|
||||
groups.forEach { it.initModels() }
|
||||
addView(recycler)
|
||||
}
|
||||
|
||||
/**
|
||||
* Adapter of the recycler view.
|
||||
*/
|
||||
inner class Adapter(items: List<Item>) : ExtendedNavigationView.Adapter(items) {
|
||||
|
||||
override fun onItemClicked(item: Item) {
|
||||
if (item is GroupedItem) {
|
||||
item.group.onItemClicked(item)
|
||||
onGroupClicked(item.group)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -3,17 +3,28 @@ package eu.kanade.tachiyomi.ui.manga.chapter
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.graphics.drawable.DrawableCompat
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.databinding.MangaChaptersHeaderBinding
|
||||
import eu.kanade.tachiyomi.ui.manga.MangaController
|
||||
import eu.kanade.tachiyomi.util.system.getResourceColor
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.merge
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import reactivecircus.flowbinding.android.view.clicks
|
||||
|
||||
class MangaChaptersHeaderAdapter :
|
||||
class MangaChaptersHeaderAdapter(
|
||||
private val controller: MangaController
|
||||
) :
|
||||
RecyclerView.Adapter<MangaChaptersHeaderAdapter.HeaderViewHolder>() {
|
||||
|
||||
private var numChapters: Int? = null
|
||||
private var hasActiveFilters: Boolean = false
|
||||
|
||||
private val scope = CoroutineScope(Job() + Dispatchers.Main)
|
||||
private lateinit var binding: MangaChaptersHeaderBinding
|
||||
@ -35,13 +46,31 @@ class MangaChaptersHeaderAdapter :
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
fun setHasActiveFilters(hasActiveFilters: Boolean) {
|
||||
this.hasActiveFilters = hasActiveFilters
|
||||
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
|
||||
inner class HeaderViewHolder(private val view: View) : RecyclerView.ViewHolder(view) {
|
||||
@ExperimentalCoroutinesApi
|
||||
fun bind() {
|
||||
binding.chaptersLabel.text = if (numChapters == null) {
|
||||
view.context.getString(R.string.chapters)
|
||||
} else {
|
||||
view.context.resources.getQuantityString(R.plurals.manga_num_chapters, numChapters!!, numChapters)
|
||||
}
|
||||
|
||||
val filterColor = if (hasActiveFilters) {
|
||||
view.context.getResourceColor(R.attr.colorFilterActive)
|
||||
} else {
|
||||
view.context.getResourceColor(R.attr.colorOnPrimary)
|
||||
}
|
||||
DrawableCompat.setTint(binding.btnChaptersFilter.icon, filterColor)
|
||||
|
||||
merge(view.clicks(), binding.btnChaptersFilter.clicks())
|
||||
.onEach { controller.showSettingsSheet() }
|
||||
.launchIn(scope)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,20 +1,38 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingTop="16dp"
|
||||
android:paddingTop="4dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:paddingBottom="8dp"
|
||||
android:paddingBottom="4dp"
|
||||
tools:context=".ui.browse.source.browse.BrowseSourceController">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/chapters_label"
|
||||
style="@style/TextAppearance.Regular.SubHeading"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/chapters"
|
||||
android:textIsSelectable="false" />
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/btn_chapters_filter"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</RelativeLayout>
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_chapters_filter"
|
||||
style="@style/Theme.Widget.Button.Icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/action_filter"
|
||||
app:icon="@drawable/ic_filter_list_24dp"
|
||||
app:iconTint="?attr/colorOnPrimary"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
@ -1,114 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<item
|
||||
android:id="@+id/action_filter"
|
||||
android:icon="@drawable/ic_filter_list_24dp"
|
||||
android:title="@string/action_filter"
|
||||
app:iconTint="?attr/colorOnPrimary"
|
||||
app:showAsAction="ifRoom">
|
||||
<menu>
|
||||
<item
|
||||
android:id="@+id/action_filter_read"
|
||||
android:checkable="true"
|
||||
android:title="@string/action_filter_read" />
|
||||
<item
|
||||
android:id="@+id/action_filter_unread"
|
||||
android:checkable="true"
|
||||
android:title="@string/action_filter_unread" />
|
||||
<item
|
||||
android:id="@+id/action_filter_downloaded"
|
||||
android:checkable="true"
|
||||
android:title="@string/action_filter_downloaded" />
|
||||
<item
|
||||
android:id="@+id/action_filter_bookmarked"
|
||||
android:checkable="true"
|
||||
android:title="@string/action_filter_bookmarked" />
|
||||
<item
|
||||
android:id="@+id/action_filter_empty"
|
||||
android:title="@string/action_filter_empty" />
|
||||
</menu>
|
||||
</item>
|
||||
|
||||
<item
|
||||
android:icon="@drawable/ic_sort_24dp"
|
||||
android:title="@string/sorting_mode"
|
||||
app:iconTint="?attr/colorOnPrimary"
|
||||
app:showAsAction="ifRoom">
|
||||
<menu>
|
||||
<group android:checkableBehavior="single">
|
||||
<item
|
||||
android:id="@+id/sort_by_source"
|
||||
android:title="@string/sort_by_source" />
|
||||
<item
|
||||
android:id="@+id/sort_by_number"
|
||||
android:title="@string/sort_by_number" />
|
||||
<item
|
||||
android:id="@+id/sort_by_upload_date"
|
||||
android:title="@string/sort_by_upload_date" />
|
||||
</group>
|
||||
|
||||
<item
|
||||
android:id="@+id/action_sort_descending"
|
||||
android:checkable="true"
|
||||
android:title="@string/action_sort_descending" />
|
||||
</menu>
|
||||
</item>
|
||||
|
||||
<item
|
||||
android:title="@string/action_display_mode"
|
||||
app:showAsAction="never">
|
||||
<menu>
|
||||
<group android:checkableBehavior="single">
|
||||
<item
|
||||
android:id="@+id/display_title"
|
||||
android:title="@string/show_title" />
|
||||
<item
|
||||
android:id="@+id/display_chapter_number"
|
||||
android:title="@string/show_chapter_number" />
|
||||
</group>
|
||||
</menu>
|
||||
</item>
|
||||
|
||||
<item
|
||||
android:id="@+id/download_group"
|
||||
android:title="@string/manga_download"
|
||||
app:showAsAction="never">
|
||||
<menu>
|
||||
<item
|
||||
android:id="@+id/download_next"
|
||||
android:title="@string/download_1" />
|
||||
<item
|
||||
android:id="@+id/download_next_5"
|
||||
android:title="@string/download_5" />
|
||||
<item
|
||||
android:id="@+id/download_next_10"
|
||||
android:title="@string/download_10" />
|
||||
<item
|
||||
android:id="@+id/download_custom"
|
||||
android:title="@string/download_custom" />
|
||||
<item
|
||||
android:id="@+id/download_unread"
|
||||
android:title="@string/download_unread" />
|
||||
<item
|
||||
android:id="@+id/download_all"
|
||||
android:title="@string/download_all" />
|
||||
</menu>
|
||||
</item>
|
||||
|
||||
<item
|
||||
android:id="@+id/action_edit_categories"
|
||||
android:title="@string/action_edit_categories"
|
||||
app:showAsAction="never" />
|
||||
|
||||
<item
|
||||
android:id="@+id/action_edit_cover"
|
||||
android:title="@string/action_edit_cover"
|
||||
app:showAsAction="never" />
|
||||
|
||||
<item
|
||||
android:id="@+id/action_migrate"
|
||||
android:title="@string/action_migrate"
|
||||
app:showAsAction="never" />
|
||||
</menu>
|
47
app/src/main/res/menu/manga.xml
Normal file
47
app/src/main/res/menu/manga.xml
Normal file
@ -0,0 +1,47 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<item
|
||||
android:id="@+id/download_group"
|
||||
android:icon="@drawable/ic_get_app_24dp"
|
||||
android:title="@string/manga_download"
|
||||
app:iconTint="?attr/colorOnPrimary"
|
||||
app:showAsAction="ifRoom">
|
||||
<menu>
|
||||
<item
|
||||
android:id="@+id/download_next"
|
||||
android:title="@string/download_1" />
|
||||
<item
|
||||
android:id="@+id/download_next_5"
|
||||
android:title="@string/download_5" />
|
||||
<item
|
||||
android:id="@+id/download_next_10"
|
||||
android:title="@string/download_10" />
|
||||
<item
|
||||
android:id="@+id/download_custom"
|
||||
android:title="@string/download_custom" />
|
||||
<item
|
||||
android:id="@+id/download_unread"
|
||||
android:title="@string/download_unread" />
|
||||
<item
|
||||
android:id="@+id/download_all"
|
||||
android:title="@string/download_all" />
|
||||
</menu>
|
||||
</item>
|
||||
|
||||
<item
|
||||
android:id="@+id/action_edit_categories"
|
||||
android:title="@string/action_edit_categories"
|
||||
app:showAsAction="never" />
|
||||
|
||||
<item
|
||||
android:id="@+id/action_edit_cover"
|
||||
android:title="@string/action_edit_cover"
|
||||
app:showAsAction="never" />
|
||||
|
||||
<item
|
||||
android:id="@+id/action_migrate"
|
||||
android:title="@string/action_migrate"
|
||||
app:showAsAction="never" />
|
||||
</menu>
|
Loading…
Reference in New Issue
Block a user