Explorar o código

Added category-wise display setting (#5232)

* Added category-wise display setting

Co-authored-by: Rogavactive <[email protected]>

* Use flag instead of preference

* Remove database call in LibraryItem

* Remove unnecessary code

Co-authored-by: Rogavactive <[email protected]>
Andreas %!s(int64=3) %!d(string=hai) anos
pai
achega
a906e9b302

+ 13 - 0
app/src/main/java/eu/kanade/tachiyomi/data/database/models/Category.kt

@@ -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
         }

+ 2 - 0
app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt

@@ -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"

+ 2 - 0
app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt

@@ -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)

+ 15 - 5
app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryView.kt

@@ -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 {

+ 3 - 1
app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryController.kt

@@ -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>>) {

+ 20 - 3
app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryItem.kt

@@ -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

+ 17 - 2
app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt

@@ -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 }
             }
     }
 

+ 72 - 12
app/src/main/java/eu/kanade/tachiyomi/ui/library/LibrarySettingsSheet.kt

@@ -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,16 +294,40 @@ 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
+                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")
                     }
-                )
 
-                item.group.items.forEach { adapter.notifyItemChanged(it) }
+                    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")
+                        }
+                    )
+                }
             }
         }
 
@@ -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

+ 6 - 0
app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsLibraryController.kt

@@ -124,6 +124,12 @@ class SettingsLibraryController : SettingsController() {
                     true
                 }
             }
+
+            switchPreference {
+                key = Keys.categorizedDisplay
+                titleRes = R.string.categorized_display_settings
+                defaultValue = false
+            }
         }
 
         preferenceCategory {

+ 1 - 1
app/src/main/res/layout/library_list_recycler.xml

@@ -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"

+ 1 - 0
app/src/main/res/values/strings.xml

@@ -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>