mirror of
https://github.com/tachiyomiorg/tachiyomi.git
synced 2024-12-22 19:41:50 +01:00
Use bottom sheet for library settings
This commit is contained in:
parent
0a5461cbea
commit
488f81ef74
@ -15,8 +15,6 @@ import androidx.appcompat.app.AppCompatActivity
|
|||||||
import androidx.appcompat.view.ActionMode
|
import androidx.appcompat.view.ActionMode
|
||||||
import androidx.appcompat.widget.SearchView
|
import androidx.appcompat.widget.SearchView
|
||||||
import androidx.core.graphics.drawable.DrawableCompat
|
import androidx.core.graphics.drawable.DrawableCompat
|
||||||
import androidx.core.view.GravityCompat
|
|
||||||
import androidx.drawerlayout.widget.DrawerLayout
|
|
||||||
import com.bluelinelabs.conductor.ControllerChangeHandler
|
import com.bluelinelabs.conductor.ControllerChangeHandler
|
||||||
import com.bluelinelabs.conductor.ControllerChangeType
|
import com.bluelinelabs.conductor.ControllerChangeType
|
||||||
import com.f2prateek.rx.preferences.Preference
|
import com.f2prateek.rx.preferences.Preference
|
||||||
@ -33,19 +31,16 @@ import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
|||||||
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.NucleusController
|
import eu.kanade.tachiyomi.ui.base.controller.NucleusController
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.RootController
|
import eu.kanade.tachiyomi.ui.base.controller.RootController
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.SecondaryDrawerController
|
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.TabbedController
|
import eu.kanade.tachiyomi.ui.base.controller.TabbedController
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
|
import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
|
||||||
import eu.kanade.tachiyomi.ui.main.MainActivity
|
import eu.kanade.tachiyomi.ui.main.MainActivity
|
||||||
import eu.kanade.tachiyomi.ui.manga.MangaController
|
import eu.kanade.tachiyomi.ui.manga.MangaController
|
||||||
import eu.kanade.tachiyomi.util.system.getResourceColor
|
import eu.kanade.tachiyomi.util.system.getResourceColor
|
||||||
import eu.kanade.tachiyomi.util.system.toast
|
import eu.kanade.tachiyomi.util.system.toast
|
||||||
import eu.kanade.tachiyomi.util.view.inflate
|
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import kotlinx.android.synthetic.main.library_controller.action_toolbar
|
import kotlinx.android.synthetic.main.library_controller.action_toolbar
|
||||||
import kotlinx.android.synthetic.main.library_controller.empty_view
|
import kotlinx.android.synthetic.main.library_controller.empty_view
|
||||||
import kotlinx.android.synthetic.main.library_controller.library_pager
|
import kotlinx.android.synthetic.main.library_controller.library_pager
|
||||||
import kotlinx.android.synthetic.main.main_activity.drawer
|
|
||||||
import kotlinx.android.synthetic.main.main_activity.tabs
|
import kotlinx.android.synthetic.main.main_activity.tabs
|
||||||
import rx.Subscription
|
import rx.Subscription
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
@ -58,7 +53,6 @@ class LibraryController(
|
|||||||
) : NucleusController<LibraryPresenter>(bundle),
|
) : NucleusController<LibraryPresenter>(bundle),
|
||||||
RootController,
|
RootController,
|
||||||
TabbedController,
|
TabbedController,
|
||||||
SecondaryDrawerController,
|
|
||||||
ActionMode.Callback,
|
ActionMode.Callback,
|
||||||
ChangeMangaCategoriesDialog.Listener,
|
ChangeMangaCategoriesDialog.Listener,
|
||||||
DeleteLibraryMangasDialog.Listener {
|
DeleteLibraryMangasDialog.Listener {
|
||||||
@ -118,14 +112,9 @@ class LibraryController(
|
|||||||
private var adapter: LibraryAdapter? = null
|
private var adapter: LibraryAdapter? = null
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Navigation view containing filter/sort/display items.
|
* Sheet containing filter/sort/display items.
|
||||||
*/
|
*/
|
||||||
private var navView: LibraryNavigationView? = null
|
private var settingsSheet: LibrarySettingsSheet? = null
|
||||||
|
|
||||||
/**
|
|
||||||
* Drawer listener to allow swipe only for closing the drawer.
|
|
||||||
*/
|
|
||||||
private var drawerListener: DrawerLayout.DrawerListener? = null
|
|
||||||
|
|
||||||
private var tabsVisibilityRelay: BehaviorRelay<Boolean> = BehaviorRelay.create(false)
|
private var tabsVisibilityRelay: BehaviorRelay<Boolean> = BehaviorRelay.create(false)
|
||||||
|
|
||||||
@ -169,6 +158,15 @@ class LibraryController(
|
|||||||
if (selectedMangas.isNotEmpty()) {
|
if (selectedMangas.isNotEmpty()) {
|
||||||
createActionModeIfNeeded()
|
createActionModeIfNeeded()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
settingsSheet = LibrarySettingsSheet(activity!!) { group ->
|
||||||
|
when (group) {
|
||||||
|
is LibrarySettingsSheet.Settings.FilterGroup -> onFilterChanged()
|
||||||
|
is LibrarySettingsSheet.Settings.SortGroup -> onSortChanged()
|
||||||
|
is LibrarySettingsSheet.Settings.DisplayGroup -> reattachAdapter()
|
||||||
|
is LibrarySettingsSheet.Settings.BadgeGroup -> onDownloadBadgeChanged()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onChangeStarted(handler: ControllerChangeHandler, type: ControllerChangeType) {
|
override fun onChangeStarted(handler: ControllerChangeHandler, type: ControllerChangeType) {
|
||||||
@ -184,32 +182,12 @@ class LibraryController(
|
|||||||
action_toolbar.destroy()
|
action_toolbar.destroy()
|
||||||
adapter?.onDestroy()
|
adapter?.onDestroy()
|
||||||
adapter = null
|
adapter = null
|
||||||
|
settingsSheet = null
|
||||||
tabsVisibilitySubscription?.unsubscribe()
|
tabsVisibilitySubscription?.unsubscribe()
|
||||||
tabsVisibilitySubscription = null
|
tabsVisibilitySubscription = null
|
||||||
super.onDestroyView(view)
|
super.onDestroyView(view)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun createSecondaryDrawer(drawer: DrawerLayout): ViewGroup {
|
|
||||||
val view = drawer.inflate(R.layout.library_drawer) as LibraryNavigationView
|
|
||||||
navView = view
|
|
||||||
drawer.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED, GravityCompat.END)
|
|
||||||
|
|
||||||
navView?.onGroupClicked = { group ->
|
|
||||||
when (group) {
|
|
||||||
is LibraryNavigationView.FilterGroup -> onFilterChanged()
|
|
||||||
is LibraryNavigationView.SortGroup -> onSortChanged()
|
|
||||||
is LibraryNavigationView.DisplayGroup -> reattachAdapter()
|
|
||||||
is LibraryNavigationView.BadgeGroup -> onDownloadBadgeChanged()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return view
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun cleanupSecondaryDrawer(drawer: DrawerLayout) {
|
|
||||||
navView = null
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun configureTabs(tabs: TabLayout) {
|
override fun configureTabs(tabs: TabLayout) {
|
||||||
with(tabs) {
|
with(tabs) {
|
||||||
tabGravity = TabLayout.GRAVITY_CENTER
|
tabGravity = TabLayout.GRAVITY_CENTER
|
||||||
@ -231,6 +209,10 @@ class LibraryController(
|
|||||||
tabsVisibilitySubscription = null
|
tabsVisibilitySubscription = null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun showSettingsSheet() {
|
||||||
|
settingsSheet?.show()
|
||||||
|
}
|
||||||
|
|
||||||
fun onNextLibraryUpdate(categories: List<Category>, mangaMap: Map<Int, List<LibraryItem>>) {
|
fun onNextLibraryUpdate(categories: List<Category>, mangaMap: Map<Int, List<LibraryItem>>) {
|
||||||
val view = view ?: return
|
val view = view ?: return
|
||||||
val adapter = adapter ?: return
|
val adapter = adapter ?: return
|
||||||
@ -364,12 +346,12 @@ class LibraryController(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onPrepareOptionsMenu(menu: Menu) {
|
override fun onPrepareOptionsMenu(menu: Menu) {
|
||||||
val navView = navView ?: return
|
val settingsSheet = settingsSheet ?: return
|
||||||
|
|
||||||
val filterItem = menu.findItem(R.id.action_filter)
|
val filterItem = menu.findItem(R.id.action_filter)
|
||||||
|
|
||||||
// Tint icon if there's a filter active
|
// Tint icon if there's a filter active
|
||||||
if (navView.hasActiveFilters()) {
|
if (settingsSheet.hasActiveFilters()) {
|
||||||
val filterColor = activity!!.getResourceColor(R.attr.colorFilterActive)
|
val filterColor = activity!!.getResourceColor(R.attr.colorFilterActive)
|
||||||
DrawableCompat.setTint(filterItem.icon, filterColor)
|
DrawableCompat.setTint(filterItem.icon, filterColor)
|
||||||
}
|
}
|
||||||
@ -378,9 +360,7 @@ class LibraryController(
|
|||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
when (item.itemId) {
|
when (item.itemId) {
|
||||||
R.id.action_search -> expandActionViewFromInteraction = true
|
R.id.action_search -> expandActionViewFromInteraction = true
|
||||||
R.id.action_filter -> {
|
R.id.action_filter -> showSettingsSheet()
|
||||||
navView?.let { activity?.drawer?.openDrawer(GravityCompat.END) }
|
|
||||||
}
|
|
||||||
R.id.action_update_library -> {
|
R.id.action_update_library -> {
|
||||||
activity?.let { LibraryUpdateService.start(it) }
|
activity?.let { LibraryUpdateService.start(it) }
|
||||||
}
|
}
|
||||||
|
@ -1,216 +0,0 @@
|
|||||||
package eu.kanade.tachiyomi.ui.library
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.util.AttributeSet
|
|
||||||
import eu.kanade.tachiyomi.R
|
|
||||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
|
||||||
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
|
||||||
import eu.kanade.tachiyomi.widget.ExtendedNavigationView
|
|
||||||
import eu.kanade.tachiyomi.widget.ExtendedNavigationView.Item.MultiSort.Companion.SORT_ASC
|
|
||||||
import eu.kanade.tachiyomi.widget.ExtendedNavigationView.Item.MultiSort.Companion.SORT_DESC
|
|
||||||
import eu.kanade.tachiyomi.widget.ExtendedNavigationView.Item.MultiSort.Companion.SORT_NONE
|
|
||||||
import uy.kohesive.injekt.injectLazy
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The navigation view shown in a drawer with the different options to show the library.
|
|
||||||
*/
|
|
||||||
class LibraryNavigationView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
|
|
||||||
ExtendedNavigationView(context, attrs) {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Preferences helper.
|
|
||||||
*/
|
|
||||||
private val preferences: PreferencesHelper by injectLazy()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* List of groups shown in the view.
|
|
||||||
*/
|
|
||||||
private val groups = listOf(FilterGroup(), SortGroup(), DisplayGroup(), BadgeGroup())
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adapter instance.
|
|
||||||
*/
|
|
||||||
private val adapter = Adapter(groups.map { it.createItems() }.flatten())
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Click listener to notify the parent fragment when an item from a group is clicked.
|
|
||||||
*/
|
|
||||||
var onGroupClicked: (Group) -> Unit = {}
|
|
||||||
|
|
||||||
init {
|
|
||||||
recycler.adapter = adapter
|
|
||||||
addView(recycler)
|
|
||||||
|
|
||||||
groups.forEach { it.initModels() }
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if there's at least one filter from [FilterGroup] active.
|
|
||||||
*/
|
|
||||||
fun hasActiveFilters(): Boolean {
|
|
||||||
return (groups[0] as FilterGroup).items.any { it.checked }
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Filters group (unread, downloaded, ...).
|
|
||||||
*/
|
|
||||||
inner class FilterGroup : Group {
|
|
||||||
|
|
||||||
private val downloaded = Item.CheckboxGroup(R.string.action_filter_downloaded, this)
|
|
||||||
|
|
||||||
private val unread = Item.CheckboxGroup(R.string.action_filter_unread, this)
|
|
||||||
|
|
||||||
private val completed = Item.CheckboxGroup(R.string.completed, this)
|
|
||||||
|
|
||||||
override val items = listOf(downloaded, unread, completed)
|
|
||||||
|
|
||||||
override val header = Item.Header(R.string.action_filter)
|
|
||||||
|
|
||||||
override val footer = Item.Separator()
|
|
||||||
|
|
||||||
override fun initModels() {
|
|
||||||
downloaded.checked = preferences.filterDownloaded().getOrDefault()
|
|
||||||
unread.checked = preferences.filterUnread().getOrDefault()
|
|
||||||
completed.checked = preferences.filterCompleted().getOrDefault()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onItemClicked(item: Item) {
|
|
||||||
item as Item.CheckboxGroup
|
|
||||||
item.checked = !item.checked
|
|
||||||
when (item) {
|
|
||||||
downloaded -> preferences.filterDownloaded().set(item.checked)
|
|
||||||
unread -> preferences.filterUnread().set(item.checked)
|
|
||||||
completed -> preferences.filterCompleted().set(item.checked)
|
|
||||||
}
|
|
||||||
|
|
||||||
adapter.notifyItemChanged(item)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sorting group (alphabetically, by last read, ...) and ascending or descending.
|
|
||||||
*/
|
|
||||||
inner class SortGroup : Group {
|
|
||||||
|
|
||||||
private val alphabetically = Item.MultiSort(R.string.action_sort_alpha, this)
|
|
||||||
|
|
||||||
private val total = Item.MultiSort(R.string.action_sort_total, this)
|
|
||||||
|
|
||||||
private val lastRead = Item.MultiSort(R.string.action_sort_last_read, this)
|
|
||||||
|
|
||||||
private val lastChecked = Item.MultiSort(R.string.action_sort_last_checked, this)
|
|
||||||
|
|
||||||
private val unread = Item.MultiSort(R.string.action_filter_unread, this)
|
|
||||||
|
|
||||||
private val latestChapter = Item.MultiSort(R.string.action_sort_latest_chapter, this)
|
|
||||||
|
|
||||||
override val items = listOf(alphabetically, lastRead, lastChecked, unread, total, latestChapter)
|
|
||||||
|
|
||||||
override val header = Item.Header(R.string.action_sort)
|
|
||||||
|
|
||||||
override val footer = Item.Separator()
|
|
||||||
|
|
||||||
override fun initModels() {
|
|
||||||
val sorting = preferences.librarySortingMode().getOrDefault()
|
|
||||||
val order = if (preferences.librarySortingAscending().getOrDefault())
|
|
||||||
SORT_ASC else SORT_DESC
|
|
||||||
|
|
||||||
alphabetically.state = if (sorting == LibrarySort.ALPHA) order else SORT_NONE
|
|
||||||
lastRead.state = if (sorting == LibrarySort.LAST_READ) order else SORT_NONE
|
|
||||||
lastChecked.state = if (sorting == LibrarySort.LAST_CHECKED) order else SORT_NONE
|
|
||||||
unread.state = if (sorting == LibrarySort.UNREAD) order else SORT_NONE
|
|
||||||
total.state = if (sorting == LibrarySort.TOTAL) order else SORT_NONE
|
|
||||||
latestChapter.state = if (sorting == LibrarySort.LATEST_CHAPTER) order else SORT_NONE
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onItemClicked(item: Item) {
|
|
||||||
item as Item.MultiStateGroup
|
|
||||||
val prevState = item.state
|
|
||||||
|
|
||||||
item.group.items.forEach { (it as Item.MultiStateGroup).state = SORT_NONE }
|
|
||||||
item.state = when (prevState) {
|
|
||||||
SORT_NONE -> SORT_ASC
|
|
||||||
SORT_ASC -> SORT_DESC
|
|
||||||
SORT_DESC -> SORT_ASC
|
|
||||||
else -> throw Exception("Unknown state")
|
|
||||||
}
|
|
||||||
|
|
||||||
preferences.librarySortingMode().set(when (item) {
|
|
||||||
alphabetically -> LibrarySort.ALPHA
|
|
||||||
lastRead -> LibrarySort.LAST_READ
|
|
||||||
lastChecked -> LibrarySort.LAST_CHECKED
|
|
||||||
unread -> LibrarySort.UNREAD
|
|
||||||
total -> LibrarySort.TOTAL
|
|
||||||
latestChapter -> LibrarySort.LATEST_CHAPTER
|
|
||||||
else -> throw Exception("Unknown sorting")
|
|
||||||
})
|
|
||||||
preferences.librarySortingAscending().set(item.state == SORT_ASC)
|
|
||||||
|
|
||||||
item.group.items.forEach { adapter.notifyItemChanged(it) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inner class BadgeGroup : Group {
|
|
||||||
private val downloadBadge = Item.CheckboxGroup(R.string.action_display_download_badge, this)
|
|
||||||
override val header = null
|
|
||||||
override val footer = null
|
|
||||||
override val items = listOf(downloadBadge)
|
|
||||||
override fun initModels() {
|
|
||||||
downloadBadge.checked = preferences.downloadBadge().getOrDefault()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onItemClicked(item: Item) {
|
|
||||||
item as Item.CheckboxGroup
|
|
||||||
item.checked = !item.checked
|
|
||||||
preferences.downloadBadge().set((item.checked))
|
|
||||||
adapter.notifyItemChanged(item)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Display group, to show the library as a list or a grid.
|
|
||||||
*/
|
|
||||||
inner class DisplayGroup : Group {
|
|
||||||
|
|
||||||
private val grid = Item.Radio(R.string.action_display_grid, this)
|
|
||||||
|
|
||||||
private val list = Item.Radio(R.string.action_display_list, this)
|
|
||||||
|
|
||||||
override val items = listOf(grid, list)
|
|
||||||
|
|
||||||
override val header = Item.Header(R.string.action_display)
|
|
||||||
|
|
||||||
override val footer = null
|
|
||||||
|
|
||||||
override fun initModels() {
|
|
||||||
val asList = preferences.libraryAsList().getOrDefault()
|
|
||||||
grid.checked = !asList
|
|
||||||
list.checked = asList
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
preferences.libraryAsList().set(item == list)
|
|
||||||
|
|
||||||
item.group.items.forEach { adapter.notifyItemChanged(it) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,243 @@
|
|||||||
|
package eu.kanade.tachiyomi.ui.library
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.content.Context
|
||||||
|
import android.util.AttributeSet
|
||||||
|
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||||
|
import eu.kanade.tachiyomi.R
|
||||||
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
|
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
||||||
|
import eu.kanade.tachiyomi.widget.ExtendedNavigationView
|
||||||
|
import uy.kohesive.injekt.injectLazy
|
||||||
|
|
||||||
|
class LibrarySettingsSheet(
|
||||||
|
activity: Activity,
|
||||||
|
onGroupClickListener: (ExtendedNavigationView.Group) -> Unit
|
||||||
|
) : BottomSheetDialog(activity) {
|
||||||
|
|
||||||
|
private var navView: Settings
|
||||||
|
|
||||||
|
init {
|
||||||
|
navView = Settings(activity)
|
||||||
|
navView.onGroupClicked = onGroupClickListener
|
||||||
|
|
||||||
|
setContentView(navView)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun hasActiveFilters(): Boolean {
|
||||||
|
return navView.hasActiveFilters()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The navigation view shown in the sheet with the different options to show the library.
|
||||||
|
*/
|
||||||
|
class Settings @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
|
||||||
|
ExtendedNavigationView(context, attrs) {
|
||||||
|
|
||||||
|
private val preferences: PreferencesHelper by injectLazy()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of groups shown in the view.
|
||||||
|
*/
|
||||||
|
private val groups = listOf(FilterGroup(), SortGroup(), DisplayGroup(), BadgeGroup())
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adapter instance.
|
||||||
|
*/
|
||||||
|
private val adapter = Adapter(groups.map { it.createItems() }.flatten())
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Click listener to notify the parent fragment when an item from a group is clicked.
|
||||||
|
*/
|
||||||
|
var onGroupClicked: (Group) -> Unit = {}
|
||||||
|
|
||||||
|
init {
|
||||||
|
recycler.adapter = adapter
|
||||||
|
addView(recycler)
|
||||||
|
|
||||||
|
groups.forEach { it.initModels() }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if there's at least one filter from [FilterGroup] active.
|
||||||
|
*/
|
||||||
|
fun hasActiveFilters(): Boolean {
|
||||||
|
return (groups[0] as FilterGroup).items.any { it.checked }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filters group (unread, downloaded, ...).
|
||||||
|
*/
|
||||||
|
inner class FilterGroup : Group {
|
||||||
|
|
||||||
|
private val downloaded = Item.CheckboxGroup(R.string.action_filter_downloaded, this)
|
||||||
|
|
||||||
|
private val unread = Item.CheckboxGroup(R.string.action_filter_unread, this)
|
||||||
|
|
||||||
|
private val completed = Item.CheckboxGroup(R.string.completed, this)
|
||||||
|
|
||||||
|
override val items = listOf(downloaded, unread, completed)
|
||||||
|
|
||||||
|
override val header = Item.Header(R.string.action_filter)
|
||||||
|
|
||||||
|
override val footer = Item.Separator()
|
||||||
|
|
||||||
|
override fun initModels() {
|
||||||
|
downloaded.checked = preferences.filterDownloaded().getOrDefault()
|
||||||
|
unread.checked = preferences.filterUnread().getOrDefault()
|
||||||
|
completed.checked = preferences.filterCompleted().getOrDefault()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onItemClicked(item: Item) {
|
||||||
|
item as Item.CheckboxGroup
|
||||||
|
item.checked = !item.checked
|
||||||
|
when (item) {
|
||||||
|
downloaded -> preferences.filterDownloaded().set(item.checked)
|
||||||
|
unread -> preferences.filterUnread().set(item.checked)
|
||||||
|
completed -> preferences.filterCompleted().set(item.checked)
|
||||||
|
}
|
||||||
|
|
||||||
|
adapter.notifyItemChanged(item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sorting group (alphabetically, by last read, ...) and ascending or descending.
|
||||||
|
*/
|
||||||
|
inner class SortGroup : Group {
|
||||||
|
|
||||||
|
private val alphabetically = Item.MultiSort(R.string.action_sort_alpha, this)
|
||||||
|
|
||||||
|
private val total = Item.MultiSort(R.string.action_sort_total, this)
|
||||||
|
|
||||||
|
private val lastRead = Item.MultiSort(R.string.action_sort_last_read, this)
|
||||||
|
|
||||||
|
private val lastChecked = Item.MultiSort(R.string.action_sort_last_checked, this)
|
||||||
|
|
||||||
|
private val unread = Item.MultiSort(R.string.action_filter_unread, this)
|
||||||
|
|
||||||
|
private val latestChapter = Item.MultiSort(R.string.action_sort_latest_chapter, this)
|
||||||
|
|
||||||
|
override val items =
|
||||||
|
listOf(alphabetically, lastRead, lastChecked, unread, total, latestChapter)
|
||||||
|
|
||||||
|
override val header = Item.Header(R.string.action_sort)
|
||||||
|
|
||||||
|
override val footer = Item.Separator()
|
||||||
|
|
||||||
|
override fun initModels() {
|
||||||
|
val sorting = preferences.librarySortingMode().getOrDefault()
|
||||||
|
val order = if (preferences.librarySortingAscending().getOrDefault())
|
||||||
|
Item.MultiSort.SORT_ASC else Item.MultiSort.SORT_DESC
|
||||||
|
|
||||||
|
alphabetically.state =
|
||||||
|
if (sorting == LibrarySort.ALPHA) order else Item.MultiSort.SORT_NONE
|
||||||
|
lastRead.state =
|
||||||
|
if (sorting == LibrarySort.LAST_READ) order else Item.MultiSort.SORT_NONE
|
||||||
|
lastChecked.state =
|
||||||
|
if (sorting == LibrarySort.LAST_CHECKED) order else Item.MultiSort.SORT_NONE
|
||||||
|
unread.state =
|
||||||
|
if (sorting == LibrarySort.UNREAD) order else Item.MultiSort.SORT_NONE
|
||||||
|
total.state = if (sorting == LibrarySort.TOTAL) order else Item.MultiSort.SORT_NONE
|
||||||
|
latestChapter.state =
|
||||||
|
if (sorting == LibrarySort.LATEST_CHAPTER) 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")
|
||||||
|
}
|
||||||
|
|
||||||
|
preferences.librarySortingMode().set(
|
||||||
|
when (item) {
|
||||||
|
alphabetically -> LibrarySort.ALPHA
|
||||||
|
lastRead -> LibrarySort.LAST_READ
|
||||||
|
lastChecked -> LibrarySort.LAST_CHECKED
|
||||||
|
unread -> LibrarySort.UNREAD
|
||||||
|
total -> LibrarySort.TOTAL
|
||||||
|
latestChapter -> LibrarySort.LATEST_CHAPTER
|
||||||
|
else -> throw Exception("Unknown sorting")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
preferences.librarySortingAscending().set(item.state == Item.MultiSort.SORT_ASC)
|
||||||
|
|
||||||
|
item.group.items.forEach { adapter.notifyItemChanged(it) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inner class BadgeGroup : Group {
|
||||||
|
private val downloadBadge =
|
||||||
|
Item.CheckboxGroup(R.string.action_display_download_badge, this)
|
||||||
|
override val header = null
|
||||||
|
override val footer = null
|
||||||
|
override val items = listOf(downloadBadge)
|
||||||
|
override fun initModels() {
|
||||||
|
downloadBadge.checked = preferences.downloadBadge().getOrDefault()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onItemClicked(item: Item) {
|
||||||
|
item as Item.CheckboxGroup
|
||||||
|
item.checked = !item.checked
|
||||||
|
preferences.downloadBadge().set((item.checked))
|
||||||
|
adapter.notifyItemChanged(item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display group, to show the library as a list or a grid.
|
||||||
|
*/
|
||||||
|
inner class DisplayGroup : Group {
|
||||||
|
|
||||||
|
private val grid = Item.Radio(R.string.action_display_grid, this)
|
||||||
|
|
||||||
|
private val list = Item.Radio(R.string.action_display_list, this)
|
||||||
|
|
||||||
|
override val items = listOf(grid, list)
|
||||||
|
|
||||||
|
override val header = Item.Header(R.string.action_display)
|
||||||
|
|
||||||
|
override val footer = null
|
||||||
|
|
||||||
|
override fun initModels() {
|
||||||
|
val asList = preferences.libraryAsList().getOrDefault()
|
||||||
|
grid.checked = !asList
|
||||||
|
list.checked = asList
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
preferences.libraryAsList().set(item == list)
|
||||||
|
|
||||||
|
item.group.items.forEach { adapter.notifyItemChanged(it) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -86,7 +86,12 @@ class MainActivity : BaseActivity() {
|
|||||||
R.id.nav_more -> setRoot(MoreController(), id)
|
R.id.nav_more -> setRoot(MoreController(), id)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
router.popToRoot()
|
when (id) {
|
||||||
|
R.id.nav_library -> {
|
||||||
|
val controller = router.getControllerWithTag(id.toString()) as? LibraryController
|
||||||
|
controller?.showSettingsSheet()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
@ -20,8 +20,7 @@ open class ExtendedNavigationView @JvmOverloads constructor(
|
|||||||
context: Context,
|
context: Context,
|
||||||
attrs: AttributeSet? = null,
|
attrs: AttributeSet? = null,
|
||||||
defStyleAttr: Int = 0
|
defStyleAttr: Int = 0
|
||||||
) :
|
) : SimpleNavigationView(context, attrs, defStyleAttr) {
|
||||||
SimpleNavigationView(context, attrs, defStyleAttr) {
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Every item of the nav view. Generic items must belong to this list, custom items could be
|
* Every item of the nav view. Generic items must belong to this list, custom items could be
|
||||||
|
@ -28,8 +28,7 @@ open class SimpleNavigationView @JvmOverloads constructor(
|
|||||||
context: Context,
|
context: Context,
|
||||||
attrs: AttributeSet? = null,
|
attrs: AttributeSet? = null,
|
||||||
defStyleAttr: Int = 0
|
defStyleAttr: Int = 0
|
||||||
) :
|
) : ScrimInsetsFrameLayout(context, attrs, defStyleAttr) {
|
||||||
ScrimInsetsFrameLayout(context, attrs, defStyleAttr) {
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Max width of the navigation view.
|
* Max width of the navigation view.
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<eu.kanade.tachiyomi.ui.library.LibraryNavigationView xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:id="@+id/nav_view2"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_gravity="end"
|
|
||||||
android:fitsSystemWindows="false" />
|
|
Loading…
Reference in New Issue
Block a user