mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-11-04 08:08:55 +01:00 
			
		
		
		
	Added category-wise display setting (#5232)
* Added category-wise display setting Co-authored-by: Rogavactive <30288842+Rogavactive@users.noreply.github.com> * Use flag instead of preference * Remove database call in LibraryItem * Remove unnecessary code Co-authored-by: Rogavactive <30288842+Rogavactive@users.noreply.github.com>
This commit is contained in:
		@@ -12,8 +12,21 @@ interface Category : Serializable {
 | 
			
		||||
 | 
			
		||||
    var flags: Int
 | 
			
		||||
 | 
			
		||||
    private fun setFlags(flag: Int, mask: Int) {
 | 
			
		||||
        flags = flags and mask.inv() or (flag and mask)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    var displayMode: Int
 | 
			
		||||
        get() = flags and MASK
 | 
			
		||||
        set(mode) = setFlags(mode, MASK)
 | 
			
		||||
 | 
			
		||||
    companion object {
 | 
			
		||||
 | 
			
		||||
        const val COMPACT_GRID = 0b00000000
 | 
			
		||||
        const val COMFORTABLE_GRID = 0b00000001
 | 
			
		||||
        const val LIST = 0b00000010
 | 
			
		||||
        const val MASK = 0b00000011
 | 
			
		||||
 | 
			
		||||
        fun create(name: String): Category = CategoryImpl().apply {
 | 
			
		||||
            this.name = name
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -185,6 +185,8 @@ object PreferenceKeys {
 | 
			
		||||
 | 
			
		||||
    const val defaultCategory = "default_category"
 | 
			
		||||
 | 
			
		||||
    const val categorizedDisplay = "categorized_display"
 | 
			
		||||
 | 
			
		||||
    const val skipRead = "skip_read"
 | 
			
		||||
 | 
			
		||||
    const val skipFiltered = "skip_filtered"
 | 
			
		||||
 
 | 
			
		||||
@@ -284,6 +284,8 @@ class PreferencesHelper(val context: Context) {
 | 
			
		||||
 | 
			
		||||
    fun defaultCategory() = prefs.getInt(Keys.defaultCategory, -1)
 | 
			
		||||
 | 
			
		||||
    fun categorisedDisplaySettings() = flowPrefs.getBoolean(Keys.categorizedDisplay, false)
 | 
			
		||||
 | 
			
		||||
    fun skipRead() = prefs.getBoolean(Keys.skipRead, false)
 | 
			
		||||
 | 
			
		||||
    fun skipFiltered() = prefs.getBoolean(Keys.skipFiltered, true)
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,6 @@ import android.util.AttributeSet
 | 
			
		||||
import android.view.View
 | 
			
		||||
import android.widget.FrameLayout
 | 
			
		||||
import androidx.recyclerview.widget.LinearLayoutManager
 | 
			
		||||
import androidx.recyclerview.widget.RecyclerView
 | 
			
		||||
import dev.chrisbanes.insetter.applyInsetter
 | 
			
		||||
import eu.davidea.flexibleadapter.FlexibleAdapter
 | 
			
		||||
import eu.davidea.flexibleadapter.SelectableAdapter
 | 
			
		||||
@@ -56,7 +55,7 @@ class LibraryCategoryView @JvmOverloads constructor(context: Context, attrs: Att
 | 
			
		||||
    /**
 | 
			
		||||
     * Recycler view of the list of manga.
 | 
			
		||||
     */
 | 
			
		||||
    private lateinit var recycler: RecyclerView
 | 
			
		||||
    private lateinit var recycler: AutofitRecyclerView
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Adapter to hold the manga in this category.
 | 
			
		||||
@@ -73,9 +72,11 @@ class LibraryCategoryView @JvmOverloads constructor(context: Context, attrs: Att
 | 
			
		||||
    fun onCreate(controller: LibraryController, binding: LibraryCategoryBinding) {
 | 
			
		||||
        this.controller = controller
 | 
			
		||||
 | 
			
		||||
        recycler = if (preferences.libraryDisplayMode().get() == DisplayMode.LIST) {
 | 
			
		||||
            (binding.swipeRefresh.inflate(R.layout.library_list_recycler) as RecyclerView).apply {
 | 
			
		||||
                layoutManager = LinearLayoutManager(context)
 | 
			
		||||
        recycler = if (preferences.libraryDisplayMode().get() == DisplayMode.LIST &&
 | 
			
		||||
            !preferences.categorisedDisplaySettings().get()
 | 
			
		||||
        ) {
 | 
			
		||||
            (binding.swipeRefresh.inflate(R.layout.library_list_recycler) as AutofitRecyclerView).apply {
 | 
			
		||||
                spanCount = 1
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            (binding.swipeRefresh.inflate(R.layout.library_grid_recycler) as AutofitRecyclerView).apply {
 | 
			
		||||
@@ -122,6 +123,15 @@ class LibraryCategoryView @JvmOverloads constructor(context: Context, attrs: Att
 | 
			
		||||
    fun onBind(category: Category) {
 | 
			
		||||
        this.category = category
 | 
			
		||||
 | 
			
		||||
        // If displayMode should be set from category adjust manga count per row
 | 
			
		||||
        if (preferences.categorisedDisplaySettings().get()) {
 | 
			
		||||
            recycler.spanCount = if (category.displayMode == Category.LIST || (preferences.libraryDisplayMode().get() == DisplayMode.LIST && category.id == 0)) {
 | 
			
		||||
                1
 | 
			
		||||
            } else {
 | 
			
		||||
                controller.mangaPerRow
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        adapter.mode = if (controller.selectedMangas.isNotEmpty()) {
 | 
			
		||||
            SelectableAdapter.Mode.MULTI
 | 
			
		||||
        } else {
 | 
			
		||||
 
 | 
			
		||||
@@ -262,7 +262,9 @@ class LibraryController(
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun showSettingsSheet() {
 | 
			
		||||
        settingsSheet?.show()
 | 
			
		||||
        adapter?.categories?.get(binding.libraryPager.currentItem)?.let { category ->
 | 
			
		||||
            settingsSheet?.show(category)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun onNextLibraryUpdate(categories: List<Category>, mangaMap: Map<Int, List<LibraryItem>>) {
 | 
			
		||||
 
 | 
			
		||||
@@ -21,17 +21,34 @@ import eu.kanade.tachiyomi.widget.AutofitRecyclerView
 | 
			
		||||
import uy.kohesive.injekt.Injekt
 | 
			
		||||
import uy.kohesive.injekt.api.get
 | 
			
		||||
 | 
			
		||||
class LibraryItem(val manga: LibraryManga, private val libraryDisplayMode: Preference<DisplayMode>) :
 | 
			
		||||
class LibraryItem(
 | 
			
		||||
    val manga: LibraryManga,
 | 
			
		||||
    private val shouldSetFromCategory: Preference<Boolean>,
 | 
			
		||||
    private val defaultLibraryDisplayMode: Preference<DisplayMode>
 | 
			
		||||
) :
 | 
			
		||||
    AbstractFlexibleItem<LibraryHolder<*>>(), IFilterable<String> {
 | 
			
		||||
 | 
			
		||||
    private val sourceManager: SourceManager = Injekt.get()
 | 
			
		||||
 | 
			
		||||
    var displayMode: Int = -1
 | 
			
		||||
    var downloadCount = -1
 | 
			
		||||
    var unreadCount = -1
 | 
			
		||||
    var isLocal = false
 | 
			
		||||
 | 
			
		||||
    private fun getDisplayMode(): DisplayMode {
 | 
			
		||||
        return if (shouldSetFromCategory.get() && manga.category != 0) {
 | 
			
		||||
            if (displayMode != -1) {
 | 
			
		||||
                DisplayMode.values()[displayMode]
 | 
			
		||||
            } else {
 | 
			
		||||
                DisplayMode.COMPACT_GRID
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            defaultLibraryDisplayMode.get()
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun getLayoutRes(): Int {
 | 
			
		||||
        return when (libraryDisplayMode.get()) {
 | 
			
		||||
        return when (getDisplayMode()) {
 | 
			
		||||
            DisplayMode.COMPACT_GRID -> R.layout.source_compact_grid_item
 | 
			
		||||
            DisplayMode.COMFORTABLE_GRID -> R.layout.source_comfortable_grid_item
 | 
			
		||||
            DisplayMode.LIST -> R.layout.source_list_item
 | 
			
		||||
@@ -39,7 +56,7 @@ class LibraryItem(val manga: LibraryManga, private val libraryDisplayMode: Prefe
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun createViewHolder(view: View, adapter: FlexibleAdapter<IFlexible<RecyclerView.ViewHolder>>): LibraryHolder<*> {
 | 
			
		||||
        return when (libraryDisplayMode.get()) {
 | 
			
		||||
        return when (getDisplayMode()) {
 | 
			
		||||
            DisplayMode.COMPACT_GRID -> {
 | 
			
		||||
                val binding = SourceCompactGridItemBinding.bind(view)
 | 
			
		||||
                val parent = adapter.recyclerView as AutofitRecyclerView
 | 
			
		||||
 
 | 
			
		||||
@@ -312,6 +312,13 @@ class LibraryPresenter(
 | 
			
		||||
                dbCategories
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            libraryManga.forEach { (categoryId, libraryManga) ->
 | 
			
		||||
                val category = categories.first { category -> category.id == categoryId }
 | 
			
		||||
                libraryManga.forEach { libraryItem ->
 | 
			
		||||
                    libraryItem.displayMode = category.displayMode
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            this.categories = categories
 | 
			
		||||
            Library(categories, libraryManga)
 | 
			
		||||
        }
 | 
			
		||||
@@ -333,10 +340,18 @@ class LibraryPresenter(
 | 
			
		||||
     * value.
 | 
			
		||||
     */
 | 
			
		||||
    private fun getLibraryMangasObservable(): Observable<LibraryMap> {
 | 
			
		||||
        val libraryDisplayMode = preferences.libraryDisplayMode()
 | 
			
		||||
        val defaultLibraryDisplayMode = preferences.libraryDisplayMode()
 | 
			
		||||
        val shouldSetFromCategory = preferences.categorisedDisplaySettings()
 | 
			
		||||
        return db.getLibraryMangas().asRxObservable()
 | 
			
		||||
            .map { list ->
 | 
			
		||||
                list.map { LibraryItem(it, libraryDisplayMode) }.groupBy { it.manga.category }
 | 
			
		||||
                list.map { libraryManga ->
 | 
			
		||||
                    // Display mode based on user preference: take it from global library setting or category
 | 
			
		||||
                    LibraryItem(
 | 
			
		||||
                        libraryManga,
 | 
			
		||||
                        shouldSetFromCategory,
 | 
			
		||||
                        defaultLibraryDisplayMode
 | 
			
		||||
                    )
 | 
			
		||||
                }.groupBy { it.manga.category }
 | 
			
		||||
            }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,8 @@ import android.util.AttributeSet
 | 
			
		||||
import android.view.View
 | 
			
		||||
import com.bluelinelabs.conductor.Router
 | 
			
		||||
import eu.kanade.tachiyomi.R
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.Category
 | 
			
		||||
import eu.kanade.tachiyomi.data.preference.PreferenceValues.DisplayMode
 | 
			
		||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
 | 
			
		||||
import eu.kanade.tachiyomi.data.track.TrackManager
 | 
			
		||||
@@ -25,6 +27,7 @@ class LibrarySettingsSheet(
 | 
			
		||||
    val filters: Filter
 | 
			
		||||
    private val sort: Sort
 | 
			
		||||
    private val display: Display
 | 
			
		||||
    private val db: DatabaseHelper by injectLazy()
 | 
			
		||||
 | 
			
		||||
    init {
 | 
			
		||||
        filters = Filter(router.activity!!)
 | 
			
		||||
@@ -37,6 +40,16 @@ class LibrarySettingsSheet(
 | 
			
		||||
        display.onGroupClicked = onGroupClickListener
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * adjusts selected button to match real state.
 | 
			
		||||
     * @param currentCategory ID of currently shown category
 | 
			
		||||
     */
 | 
			
		||||
    fun show(currentCategory: Category) {
 | 
			
		||||
        display.currentCategory = currentCategory
 | 
			
		||||
        display.adjustDisplaySelection()
 | 
			
		||||
        super.show()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun getTabViews(): List<View> = listOf(
 | 
			
		||||
        filters,
 | 
			
		||||
        sort,
 | 
			
		||||
@@ -232,8 +245,31 @@ class LibrarySettingsSheet(
 | 
			
		||||
    inner class Display @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
 | 
			
		||||
        Settings(context, attrs) {
 | 
			
		||||
 | 
			
		||||
        private val displayGroup: DisplayGroup
 | 
			
		||||
        private val badgeGroup: BadgeGroup
 | 
			
		||||
        private val tabsGroup: TabsGroup
 | 
			
		||||
 | 
			
		||||
        init {
 | 
			
		||||
            setGroups(listOf(DisplayGroup(), BadgeGroup(), TabsGroup()))
 | 
			
		||||
            displayGroup = DisplayGroup()
 | 
			
		||||
            badgeGroup = BadgeGroup()
 | 
			
		||||
            tabsGroup = TabsGroup()
 | 
			
		||||
            setGroups(listOf(displayGroup, badgeGroup, tabsGroup))
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Refreshes Display Setting selections
 | 
			
		||||
        fun adjustDisplaySelection() {
 | 
			
		||||
            val mode = getDisplayModePreference()
 | 
			
		||||
            displayGroup.setGroupSelections(mode)
 | 
			
		||||
            displayGroup.items.forEach { adapter.notifyItemChanged(it) }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Gets user preference of currently selected display mode at current category
 | 
			
		||||
        private fun getDisplayModePreference(): DisplayMode {
 | 
			
		||||
            return if (preferences.categorisedDisplaySettings().get() && currentCategory != null && currentCategory?.id != 0) {
 | 
			
		||||
                DisplayMode.values()[currentCategory?.displayMode ?: 0]
 | 
			
		||||
            } else {
 | 
			
		||||
                preferences.libraryDisplayMode().get()
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        inner class DisplayGroup : Group {
 | 
			
		||||
@@ -247,10 +283,8 @@ class LibrarySettingsSheet(
 | 
			
		||||
            override val footer = null
 | 
			
		||||
 | 
			
		||||
            override fun initModels() {
 | 
			
		||||
                val mode = preferences.libraryDisplayMode().get()
 | 
			
		||||
                compactGrid.checked = mode == DisplayMode.COMPACT_GRID
 | 
			
		||||
                comfortableGrid.checked = mode == DisplayMode.COMFORTABLE_GRID
 | 
			
		||||
                list.checked = mode == DisplayMode.LIST
 | 
			
		||||
                val mode = getDisplayModePreference()
 | 
			
		||||
                setGroupSelections(mode)
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            override fun onItemClicked(item: Item) {
 | 
			
		||||
@@ -260,17 +294,41 @@ class LibrarySettingsSheet(
 | 
			
		||||
                item.group.items.forEach { (it as Item.Radio).checked = false }
 | 
			
		||||
                item.checked = true
 | 
			
		||||
 | 
			
		||||
                preferences.libraryDisplayMode().set(
 | 
			
		||||
                    when (item) {
 | 
			
		||||
                        compactGrid -> DisplayMode.COMPACT_GRID
 | 
			
		||||
                        comfortableGrid -> DisplayMode.COMFORTABLE_GRID
 | 
			
		||||
                        list -> DisplayMode.LIST
 | 
			
		||||
                        else -> throw NotImplementedError("Unknown display mode")
 | 
			
		||||
                    }
 | 
			
		||||
                )
 | 
			
		||||
                setDisplayModePreference(item)
 | 
			
		||||
 | 
			
		||||
                item.group.items.forEach { adapter.notifyItemChanged(it) }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Sets display group selections based on given mode
 | 
			
		||||
            fun setGroupSelections(mode: DisplayMode) {
 | 
			
		||||
                compactGrid.checked = mode == DisplayMode.COMPACT_GRID
 | 
			
		||||
                comfortableGrid.checked = mode == DisplayMode.COMFORTABLE_GRID
 | 
			
		||||
                list.checked = mode == DisplayMode.LIST
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            private fun setDisplayModePreference(item: Item) {
 | 
			
		||||
                if (preferences.categorisedDisplaySettings().get() && currentCategory != null && currentCategory?.id != 0) {
 | 
			
		||||
                    val flag = when (item) {
 | 
			
		||||
                        compactGrid -> Category.COMPACT_GRID
 | 
			
		||||
                        comfortableGrid -> Category.COMFORTABLE_GRID
 | 
			
		||||
                        list -> Category.LIST
 | 
			
		||||
                        else -> throw NotImplementedError("Unknown display mode")
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    currentCategory?.displayMode = flag
 | 
			
		||||
 | 
			
		||||
                    db.insertCategory(currentCategory!!).executeAsBlocking()
 | 
			
		||||
                } else {
 | 
			
		||||
                    preferences.libraryDisplayMode().set(
 | 
			
		||||
                        when (item) {
 | 
			
		||||
                            compactGrid -> DisplayMode.COMPACT_GRID
 | 
			
		||||
                            comfortableGrid -> DisplayMode.COMFORTABLE_GRID
 | 
			
		||||
                            list -> DisplayMode.LIST
 | 
			
		||||
                            else -> throw NotImplementedError("Unknown display mode")
 | 
			
		||||
                        }
 | 
			
		||||
                    )
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        inner class BadgeGroup : Group {
 | 
			
		||||
@@ -336,6 +394,8 @@ class LibrarySettingsSheet(
 | 
			
		||||
         */
 | 
			
		||||
        var onGroupClicked: (Group) -> Unit = {}
 | 
			
		||||
 | 
			
		||||
        var currentCategory: Category? = null
 | 
			
		||||
 | 
			
		||||
        fun setGroups(groups: List<Group>) {
 | 
			
		||||
            adapter = Adapter(groups.map { it.createItems() }.flatten())
 | 
			
		||||
            recycler.adapter = adapter
 | 
			
		||||
 
 | 
			
		||||
@@ -124,6 +124,12 @@ class SettingsLibraryController : SettingsController() {
 | 
			
		||||
                    true
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            switchPreference {
 | 
			
		||||
                key = Keys.categorizedDisplay
 | 
			
		||||
                titleRes = R.string.categorized_display_settings
 | 
			
		||||
                defaultValue = false
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        preferenceCategory {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<androidx.recyclerview.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
 | 
			
		||||
<eu.kanade.tachiyomi.widget.AutofitRecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
 | 
			
		||||
    xmlns:tools="http://schemas.android.com/tools"
 | 
			
		||||
    android:id="@+id/library_list"
 | 
			
		||||
    android:layout_width="match_parent"
 | 
			
		||||
 
 | 
			
		||||
@@ -219,6 +219,7 @@
 | 
			
		||||
 | 
			
		||||
    <string name="default_category">Default category</string>
 | 
			
		||||
    <string name="default_category_summary">Always ask</string>
 | 
			
		||||
    <string name="categorized_display_settings">Per-category display settings</string>
 | 
			
		||||
    <plurals name="num_categories">
 | 
			
		||||
        <item quantity="one">%d category</item>
 | 
			
		||||
        <item quantity="other">%d categories</item>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user