diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/database/models/Category.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/models/Category.kt index 5e040ab36..ce0a5f97f 100755 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/models/Category.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/database/models/Category.kt @@ -16,8 +16,26 @@ interface Category : Serializable { var mangaOrder: List // SY <-- + 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 + + // SY --> + const val NO_TITLE_GRID = 0b00000011 + + // SY <-- + const val MASK = 0b00000011 + fun create(name: String): Category = CategoryImpl().apply { this.name = name } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt index eb1f2c3fb..677151e49 100755 --- a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt @@ -191,6 +191,8 @@ object PreferenceKeys { const val defaultCategory = "default_category" + const val categorizedDisplay = "categorized_display" + const val skipRead = "skip_read" const val skipFiltered = "skip_filtered" diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceValues.kt b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceValues.kt index 4f2fe80e7..f63eadeae 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceValues.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceValues.kt @@ -41,12 +41,11 @@ object PreferenceValues { enum class DisplayMode { COMPACT_GRID, COMFORTABLE_GRID, + LIST, // SY --> NO_TITLE_GRID, - // SY <-- - LIST, } enum class TappingInvertMode(val shouldInvertHorizontal: Boolean = false, val shouldInvertVertical: Boolean = false) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt index 968554a86..75bcee8cf 100755 --- a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt @@ -292,6 +292,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) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryView.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryView.kt index acd301bd3..aac13a69c 100755 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryView.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryView.kt @@ -71,7 +71,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. @@ -92,9 +92,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 { @@ -154,6 +156,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 { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryController.kt index 434576102..17d33e838 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryController.kt @@ -297,7 +297,9 @@ class LibraryController( } fun showSettingsSheet() { - settingsSheet?.show() + adapter?.categories?.get(binding.libraryPager.currentItem)?.let { category -> + settingsSheet?.show(category) + } } fun onNextLibraryUpdate(categories: List, mangaMap: Map>) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryItem.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryItem.kt index 8adc36cd2..781109d87 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryItem.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryItem.kt @@ -21,11 +21,16 @@ 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) : +class LibraryItem( + val manga: LibraryManga, + private val shouldSetFromCategory: Preference, + private val defaultLibraryDisplayMode: Preference +) : AbstractFlexibleItem>(), IFilterable { private val sourceManager: SourceManager = Injekt.get() + var displayMode: Int = -1 var downloadCount = -1 var unreadCount = -1 var isLocal = false @@ -34,8 +39,20 @@ class LibraryItem(val manga: LibraryManga, private val libraryDisplayMode: Prefe var startReadingButton = false // SY <-- + 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 /* SY --> */, DisplayMode.NO_TITLE_GRID /* SY <-- */ -> R.layout.source_comfortable_grid_item DisplayMode.LIST -> R.layout.source_list_item @@ -43,7 +60,7 @@ class LibraryItem(val manga: LibraryManga, private val libraryDisplayMode: Prefe } override fun createViewHolder(view: View, adapter: FlexibleAdapter>): LibraryHolder<*> { - return when (libraryDisplayMode.get()) { + return when (val displayMode = getDisplayMode()) { DisplayMode.COMPACT_GRID -> { val binding = SourceCompactGridItemBinding.bind(view) val parent = adapter.recyclerView as AutofitRecyclerView @@ -68,7 +85,7 @@ class LibraryItem(val manga: LibraryManga, private val libraryDisplayMode: Prefe coverHeight ) } - LibraryComfortableGridHolder(view, adapter, libraryDisplayMode.get() != DisplayMode.NO_TITLE_GRID) + LibraryComfortableGridHolder(view, adapter, displayMode != DisplayMode.NO_TITLE_GRID) } DisplayMode.LIST -> { LibraryListHolder(view, adapter) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt index b75a98259..5d07f34ee 100755 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt @@ -426,6 +426,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) } @@ -468,10 +475,18 @@ class LibraryPresenter( * value. */ private fun getLibraryMangasObservable(): Observable { - 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 } } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibrarySettingsSheet.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibrarySettingsSheet.kt index ec8af250a..9857a4649 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibrarySettingsSheet.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibrarySettingsSheet.kt @@ -6,6 +6,7 @@ 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 @@ -27,6 +28,7 @@ class LibrarySettingsSheet( private val sort: Sort private val display: Display private val grouping: Grouping + private val db: DatabaseHelper by injectLazy() init { filters = Filter(router.activity!!) @@ -46,6 +48,16 @@ class LibrarySettingsSheet( sort.refreshMode() } + /** + * 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 = listOf( filters, sort, @@ -289,8 +301,39 @@ class LibrarySettingsSheet( inner class Display @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) : Settings(context, attrs) { + private val displayGroup: DisplayGroup + private val badgeGroup: BadgeGroup + + // SY --> + private val buttonsGroup: ButtonsGroup + + // SY <-- + private val tabsGroup: TabsGroup + init { - setGroups(listOf(DisplayGroup(), BadgeGroup(), /* SY --> */ ButtonsGroup(), /* SY <-- */ TabsGroup())) + displayGroup = DisplayGroup() + badgeGroup = BadgeGroup() + // SY --> + buttonsGroup = ButtonsGroup() + // SY <-- + tabsGroup = TabsGroup() + setGroups(listOf(displayGroup, badgeGroup, /* SY --> */ buttonsGroup, /* SY <-- */ 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 { @@ -309,13 +352,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 - // SY --> - noTitleGrid.checked = mode == DisplayMode.NO_TITLE_GRID - // SY <-- - list.checked = mode == DisplayMode.LIST + val mode = getDisplayModePreference() + setGroupSelections(mode) } override fun onItemClicked(item: Item) { @@ -325,20 +363,50 @@ 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 - // SY --> - noTitleGrid -> DisplayMode.NO_TITLE_GRID - // SY <-- - 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 + // SY --> + noTitleGrid.checked = mode == DisplayMode.NO_TITLE_GRID + // SY <-- + 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 + // SY --> + noTitleGrid -> Category.NO_TITLE_GRID + // SY <-- + 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 + // SY --> + noTitleGrid -> DisplayMode.NO_TITLE_GRID + // SY <-- + list -> DisplayMode.LIST + else -> throw NotImplementedError("Unknown display mode") + } + ) + } + } } inner class BadgeGroup : Group { @@ -501,6 +569,8 @@ class LibrarySettingsSheet( */ var onGroupClicked: (Group) -> Unit = {} + var currentCategory: Category? = null + fun setGroups(groups: List) { adapter = Adapter(groups.map { it.createItems() }.flatten()) recycler.adapter = adapter diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsLibraryController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsLibraryController.kt index 3001652b9..bc2f00a12 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsLibraryController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsLibraryController.kt @@ -148,6 +148,12 @@ class SettingsLibraryController : SettingsController() { true } } + + switchPreference { + key = Keys.categorizedDisplay + titleRes = R.string.categorized_display_settings + defaultValue = false + } } preferenceCategory { diff --git a/app/src/main/res/layout/library_list_recycler.xml b/app/src/main/res/layout/library_list_recycler.xml index 38f5cfdf6..2604c02bd 100755 --- a/app/src/main/res/layout/library_list_recycler.xml +++ b/app/src/main/res/layout/library_list_recycler.xml @@ -1,5 +1,5 @@ -Default category Always ask + Per-category display settings %d category %d categories