mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-11-03 23:58:55 +01:00 
			
		
		
		
	Use bottom sheet for library settings
This commit is contained in:
		@@ -15,8 +15,6 @@ import androidx.appcompat.app.AppCompatActivity
 | 
			
		||||
import androidx.appcompat.view.ActionMode
 | 
			
		||||
import androidx.appcompat.widget.SearchView
 | 
			
		||||
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.ControllerChangeType
 | 
			
		||||
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.ui.base.controller.NucleusController
 | 
			
		||||
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.withFadeTransaction
 | 
			
		||||
import eu.kanade.tachiyomi.ui.main.MainActivity
 | 
			
		||||
import eu.kanade.tachiyomi.ui.manga.MangaController
 | 
			
		||||
import eu.kanade.tachiyomi.util.system.getResourceColor
 | 
			
		||||
import eu.kanade.tachiyomi.util.system.toast
 | 
			
		||||
import eu.kanade.tachiyomi.util.view.inflate
 | 
			
		||||
import java.io.IOException
 | 
			
		||||
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.library_pager
 | 
			
		||||
import kotlinx.android.synthetic.main.main_activity.drawer
 | 
			
		||||
import kotlinx.android.synthetic.main.main_activity.tabs
 | 
			
		||||
import rx.Subscription
 | 
			
		||||
import timber.log.Timber
 | 
			
		||||
@@ -58,7 +53,6 @@ class LibraryController(
 | 
			
		||||
) : NucleusController<LibraryPresenter>(bundle),
 | 
			
		||||
        RootController,
 | 
			
		||||
        TabbedController,
 | 
			
		||||
        SecondaryDrawerController,
 | 
			
		||||
        ActionMode.Callback,
 | 
			
		||||
        ChangeMangaCategoriesDialog.Listener,
 | 
			
		||||
        DeleteLibraryMangasDialog.Listener {
 | 
			
		||||
@@ -118,14 +112,9 @@ class LibraryController(
 | 
			
		||||
    private var adapter: LibraryAdapter? = null
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Navigation view containing filter/sort/display items.
 | 
			
		||||
     * Sheet containing filter/sort/display items.
 | 
			
		||||
     */
 | 
			
		||||
    private var navView: LibraryNavigationView? = null
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Drawer listener to allow swipe only for closing the drawer.
 | 
			
		||||
     */
 | 
			
		||||
    private var drawerListener: DrawerLayout.DrawerListener? = null
 | 
			
		||||
    private var settingsSheet: LibrarySettingsSheet? = null
 | 
			
		||||
 | 
			
		||||
    private var tabsVisibilityRelay: BehaviorRelay<Boolean> = BehaviorRelay.create(false)
 | 
			
		||||
 | 
			
		||||
@@ -169,6 +158,15 @@ class LibraryController(
 | 
			
		||||
        if (selectedMangas.isNotEmpty()) {
 | 
			
		||||
            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) {
 | 
			
		||||
@@ -184,32 +182,12 @@ class LibraryController(
 | 
			
		||||
        action_toolbar.destroy()
 | 
			
		||||
        adapter?.onDestroy()
 | 
			
		||||
        adapter = null
 | 
			
		||||
        settingsSheet = null
 | 
			
		||||
        tabsVisibilitySubscription?.unsubscribe()
 | 
			
		||||
        tabsVisibilitySubscription = null
 | 
			
		||||
        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) {
 | 
			
		||||
        with(tabs) {
 | 
			
		||||
            tabGravity = TabLayout.GRAVITY_CENTER
 | 
			
		||||
@@ -231,6 +209,10 @@ class LibraryController(
 | 
			
		||||
        tabsVisibilitySubscription = null
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun showSettingsSheet() {
 | 
			
		||||
        settingsSheet?.show()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun onNextLibraryUpdate(categories: List<Category>, mangaMap: Map<Int, List<LibraryItem>>) {
 | 
			
		||||
        val view = view ?: return
 | 
			
		||||
        val adapter = adapter ?: return
 | 
			
		||||
@@ -364,12 +346,12 @@ class LibraryController(
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun onPrepareOptionsMenu(menu: Menu) {
 | 
			
		||||
        val navView = navView ?: return
 | 
			
		||||
        val settingsSheet = settingsSheet ?: return
 | 
			
		||||
 | 
			
		||||
        val filterItem = menu.findItem(R.id.action_filter)
 | 
			
		||||
 | 
			
		||||
        // Tint icon if there's a filter active
 | 
			
		||||
        if (navView.hasActiveFilters()) {
 | 
			
		||||
        if (settingsSheet.hasActiveFilters()) {
 | 
			
		||||
            val filterColor = activity!!.getResourceColor(R.attr.colorFilterActive)
 | 
			
		||||
            DrawableCompat.setTint(filterItem.icon, filterColor)
 | 
			
		||||
        }
 | 
			
		||||
@@ -378,9 +360,7 @@ class LibraryController(
 | 
			
		||||
    override fun onOptionsItemSelected(item: MenuItem): Boolean {
 | 
			
		||||
        when (item.itemId) {
 | 
			
		||||
            R.id.action_search -> expandActionViewFromInteraction = true
 | 
			
		||||
            R.id.action_filter -> {
 | 
			
		||||
                navView?.let { activity?.drawer?.openDrawer(GravityCompat.END) }
 | 
			
		||||
            }
 | 
			
		||||
            R.id.action_filter -> showSettingsSheet()
 | 
			
		||||
            R.id.action_update_library -> {
 | 
			
		||||
                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)
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                router.popToRoot()
 | 
			
		||||
                when (id) {
 | 
			
		||||
                    R.id.nav_library -> {
 | 
			
		||||
                        val controller = router.getControllerWithTag(id.toString()) as? LibraryController
 | 
			
		||||
                        controller?.showSettingsSheet()
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            true
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -20,8 +20,7 @@ open class ExtendedNavigationView @JvmOverloads constructor(
 | 
			
		||||
    context: Context,
 | 
			
		||||
    attrs: AttributeSet? = null,
 | 
			
		||||
    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
 | 
			
		||||
 
 | 
			
		||||
@@ -28,8 +28,7 @@ open class SimpleNavigationView @JvmOverloads constructor(
 | 
			
		||||
    context: Context,
 | 
			
		||||
    attrs: AttributeSet? = null,
 | 
			
		||||
    defStyleAttr: Int = 0
 | 
			
		||||
) :
 | 
			
		||||
    ScrimInsetsFrameLayout(context, attrs, defStyleAttr) {
 | 
			
		||||
) : ScrimInsetsFrameLayout(context, attrs, defStyleAttr) {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 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" />
 | 
			
		||||
		Reference in New Issue
	
	Block a user