mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-10-30 22:07:57 +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 { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user