From 4bb6dbf528d859babc5ec97c682629972ffa62a2 Mon Sep 17 00:00:00 2001 From: Jays2Kings Date: Mon, 19 Apr 2021 00:19:38 -0400 Subject: [PATCH] Option to collapse dynamic categories --- .../data/preference/PreferencesHelper.kt | 10 +++ .../tachiyomi/ui/library/LibraryController.kt | 18 +++- .../ui/library/LibraryHeaderHolder.kt | 14 +-- .../tachiyomi/ui/library/LibraryPresenter.kt | 85 +++++++++++++++---- .../ui/library/display/LibraryCategoryView.kt | 14 ++- .../display/TabbedLibraryDisplaySheet.kt | 16 +--- 6 files changed, 106 insertions(+), 51 deletions(-) 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 522d58d972..9d4d085e5f 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt @@ -69,6 +69,14 @@ operator fun com.tfcporciuncula.flow.Preference>.minusAssign(item: T) set(get() - item) } +operator fun com.tfcporciuncula.flow.Preference>.plusAssign(item: Collection) { + set(get() + item) +} + +operator fun com.tfcporciuncula.flow.Preference>.minusAssign(item: Collection) { + set(get() - item) +} + class PreferencesHelper(val context: Context) { private val prefs = PreferenceManager.getDefaultSharedPreferences(context) @@ -270,6 +278,8 @@ class PreferencesHelper(val context: Context) { fun collapsedCategories() = rxPrefs.getStringSet("collapsed_categories", mutableSetOf()) + fun collapsedDynamicCategories() = flowPrefs.getStringSet("collapsed_dynamic_categories", mutableSetOf()) + fun hiddenSources() = flowPrefs.getStringSet("hidden_catalogues", mutableSetOf()) fun pinnedCatalogues() = rxPrefs.getStringSet("pinned_catalogues", emptySet()) 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 14271ed850..da9e29fc99 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 @@ -918,10 +918,7 @@ class LibraryController( ) adapter.isLongPressDragEnabled = canDrag() binding.categoryRecycler.setCategories(presenter.categories) - displaySheet?.setExpandText( - showExpanded = !singleCategory && presenter.showAllCategories, - allExpanded = preferences.collapsedCategories().getOrDefault().isNotEmpty() - ) + displaySheet?.setExpandText(canCollapseOrExpandCategory()) if (shouldScrollToTop) { binding.libraryGridRecycler.recycler.scrollToPosition(0) shouldScrollToTop = false @@ -1382,6 +1379,19 @@ class LibraryController( presenter.toggleCategoryVisibility(catId) } + /** + * Nullable Boolean to tell is all is collapsed/expanded/applicable + * true = all categories are expanded + * false = all or some categories are collapsed + * null = is in single category mode + */ + fun canCollapseOrExpandCategory(): Boolean? { + if (singleCategory || !presenter.showAllCategories) { + return null + } + return presenter.allCategoriesExpanded() + } + override fun manageCategory(position: Int) { val category = (adapter.getItem(position) as? LibraryHeaderItem)?.category ?: return if (!category.isDynamic) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryHeaderHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryHeaderHolder.kt index 711aa6fdba..be50223739 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryHeaderHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryHeaderHolder.kt @@ -80,14 +80,6 @@ class LibraryHeaderHolder(val view: View, private val adapter: LibraryCategoryAd } val category = item.category - if (category.isDynamic) { - binding.categoryHeaderLayout.background = null - binding.categoryTitle.background = null - } else { - binding.categoryHeaderLayout.setBackgroundResource(R.drawable.list_item_selector) - binding.categoryTitle.setBackgroundResource(R.drawable.square_ripple) - } - if (category.isAlone && !category.isDynamic) binding.categoryTitle.text = "" else binding.categoryTitle.text = category.name if (category.sourceId != null) { @@ -115,7 +107,7 @@ class LibraryHeaderHolder(val view: View, private val adapter: LibraryCategoryAd when { adapter.mode == SelectableAdapter.Mode.MULTI -> { binding.checkbox.visibleIf(!category.isHidden) - binding.collapseArrow.visibleIf(category.isHidden && !adapter.isSingleCategory && !category.isDynamic) + binding.collapseArrow.visibleIf(category.isHidden && !adapter.isSingleCategory) binding.updateButton.gone() binding.catProgress.gone() setSelection() @@ -127,13 +119,13 @@ class LibraryHeaderHolder(val view: View, private val adapter: LibraryCategoryAd binding.updateButton.gone() } LibraryUpdateService.categoryInQueue(category.id) -> { - binding.collapseArrow.visibleIf(!adapter.isSingleCategory && !category.isDynamic) + binding.collapseArrow.visibleIf(!adapter.isSingleCategory) binding.checkbox.gone() binding.catProgress.visible() binding.updateButton.invisible() } else -> { - binding.collapseArrow.visibleIf(!adapter.isSingleCategory && !category.isDynamic) + binding.collapseArrow.visibleIf(!adapter.isSingleCategory) binding.catProgress.gone() binding.checkbox.gone() binding.updateButton.visibleIf(!adapter.isSingleCategory) 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 54b25f2783..a06a70b9f5 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt @@ -11,6 +11,8 @@ import eu.kanade.tachiyomi.data.database.models.MangaCategory import eu.kanade.tachiyomi.data.download.DownloadManager import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.getOrDefault +import eu.kanade.tachiyomi.data.preference.minusAssign +import eu.kanade.tachiyomi.data.preference.plusAssign import eu.kanade.tachiyomi.data.track.TrackManager import eu.kanade.tachiyomi.source.LocalSource import eu.kanade.tachiyomi.source.SourceManager @@ -581,12 +583,13 @@ class LibraryPresenter( } BY_SOURCE -> { val source = sourceManager.getOrStub(manga.source) - listOf(LibraryItem(manga, makeOrGetHeader("${source.name}◘•◘${source.id}"))) + listOf(LibraryItem(manga, makeOrGetHeader("${source.name}$sourceSplitter${source.id}"))) } else -> listOf(LibraryItem(manga, makeOrGetHeader(mapStatus(manga.status)))) } - }.flatten() + }.flatten().toMutableList() + val hiddenDynamics = preferences.collapsedDynamicCategories().get() val headers = tagItems.map { item -> Category.createCustom( item.key, @@ -594,11 +597,12 @@ class LibraryPresenter( preferences.librarySortingAscending().getOrDefault() ).apply { id = item.value.catId - if (name.contains("◘•◘")) { - val split = name.split("◘•◘") + if (name.contains(sourceSplitter)) { + val split = name.split(sourceSplitter) name = split.first() sourceId = split.last().toLongOrNull() } + isHidden = getDynamicCategoryName(this) in hiddenDynamics } }.sortedBy { if (groupType == BY_TRACK_STATUS) { @@ -607,6 +611,22 @@ class LibraryPresenter( it.name } } + headers.forEach { category -> + val catId = category.id ?: return@forEach + val headerItem = tagItems[if (category.sourceId != null) "${category.name}$sourceSplitter${category.sourceId}" else category.name] + if (category.isHidden) { + val mangaToRemove = items.filter { it.header.catId == catId } + val mergedTitle = mangaToRemove.joinToString("-") { + it.manga.title + "-" + it.manga.author + } + sectionedLibraryItems[catId] = mangaToRemove + items.removeAll { it.header.catId == catId } + if (headerItem != null) items.add( + LibraryItem(LibraryManga.createHide(catId, mergedTitle), headerItem) + ) + } + } + headers.forEachIndexed { index, category -> category.order = index } return items to headers } @@ -858,28 +878,61 @@ class LibraryPresenter( } fun toggleCategoryVisibility(categoryId: Int) { - if (categories.find { it.id == categoryId }?.isDynamic == true) return - val categoriesHidden = preferences.collapsedCategories().getOrDefault().mapNotNull { - it.toIntOrNull() - }.toMutableSet() - if (categoryId in categoriesHidden) { - categoriesHidden.remove(categoryId) + // if (categories.find { it.id == categoryId }?.isDynamic == true) return + if (groupType == BY_DEFAULT) { + val categoriesHidden = preferences.collapsedCategories().getOrDefault().mapNotNull { + it.toIntOrNull() + }.toMutableSet() + if (categoryId in categoriesHidden) { + categoriesHidden.remove(categoryId) + } else { + categoriesHidden.add(categoryId) + } + preferences.collapsedCategories() + .set(categoriesHidden.map { it.toString() }.toMutableSet()) } else { - categoriesHidden.add(categoryId) + val categoriesHidden = preferences.collapsedDynamicCategories().get().toMutableSet() + val category = getCategory(categoryId) + val dynamicName = getDynamicCategoryName(category) + if (dynamicName in categoriesHidden) { + categoriesHidden.remove(dynamicName) + } else { + categoriesHidden.add(dynamicName) + } + preferences.collapsedDynamicCategories().set(categoriesHidden) } - preferences.collapsedCategories().set(categoriesHidden.map { it.toString() }.toMutableSet()) getLibrary() } + private fun getDynamicCategoryName(category: Category): String = + groupType.toString() + dynamicCategorySplitter + (category.sourceId?.toString() ?: category.name) + fun toggleAllCategoryVisibility() { - if (preferences.collapsedCategories().getOrDefault().isEmpty()) { - preferences.collapsedCategories().set(allCategories.map { it.id.toString() }.toMutableSet()) + if (groupType == BY_DEFAULT) { + if (allCategoriesExpanded()) { + preferences.collapsedCategories() + .set(allCategories.map { it.id.toString() }.toMutableSet()) + } else { + preferences.collapsedCategories().set(mutableSetOf()) + } } else { - preferences.collapsedCategories().set(mutableSetOf()) + if (allCategoriesExpanded()) { + preferences.collapsedDynamicCategories() += categories.map { getDynamicCategoryName(it) } + } else { + preferences.collapsedDynamicCategories() -= categories.map { getDynamicCategoryName(it) } + } } getLibrary() } + fun allCategoriesExpanded(): Boolean { + return if (groupType == BY_DEFAULT) { + preferences.collapsedCategories().getOrDefault().isEmpty() + } else { + categories.none { it.isHidden } + } + } + /** download All unread */ fun downloadUnread(mangaList: List) { scope.launch { @@ -925,6 +978,8 @@ class LibraryPresenter( companion object { private var lastLibraryItems: List? = null private var lastCategories: List? = null + private const val sourceSplitter = "◘•◘" + private const val dynamicCategorySplitter = "▄╪\t▄╪\t▄" /** Give library manga to a date added based on min chapter fetch */ fun updateDB() { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/display/LibraryCategoryView.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/display/LibraryCategoryView.kt index 5704c4cc5d..64b931d2dd 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/display/LibraryCategoryView.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/display/LibraryCategoryView.kt @@ -49,13 +49,11 @@ class LibraryCategoryView @JvmOverloads constructor(context: Context, attrs: Att } } - fun showExpandCategories(show: Boolean) { - binding.expandCollapseCategories.isVisible = show - } - - fun setExpandText(expand: Boolean, animated: Boolean = true) { + fun setExpandText(allExpanded: Boolean?, animated: Boolean = true) { + binding.expandCollapseCategories.isVisible = allExpanded != null + allExpanded ?: return binding.expandCollapseCategories.setText( - if (expand) { + if (!allExpanded) { R.string.expand_all_categories } else { R.string.collapse_all_categories @@ -63,7 +61,7 @@ class LibraryCategoryView @JvmOverloads constructor(context: Context, attrs: Att ) if (animated) { binding.expandCollapseCategories.setIconResource( - if (expand) { + if (!allExpanded) { R.drawable.anim_expand_less_to_more } else { R.drawable.anim_expand_more_to_less @@ -72,7 +70,7 @@ class LibraryCategoryView @JvmOverloads constructor(context: Context, attrs: Att (binding.expandCollapseCategories.icon as? AnimatedVectorDrawable)?.start() } else { binding.expandCollapseCategories.setIconResource( - if (expand) { + if (!allExpanded) { R.drawable.ic_expand_more_24dp } else { R.drawable.ic_expand_less_24dp diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/display/TabbedLibraryDisplaySheet.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/display/TabbedLibraryDisplaySheet.kt index 603bbe2cda..31085a9e75 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/display/TabbedLibraryDisplaySheet.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/display/TabbedLibraryDisplaySheet.kt @@ -6,15 +6,11 @@ import androidx.core.content.ContextCompat import androidx.core.view.isVisible import com.bluelinelabs.conductor.Controller import eu.kanade.tachiyomi.R -import eu.kanade.tachiyomi.data.preference.PreferencesHelper -import eu.kanade.tachiyomi.data.preference.getOrDefault import eu.kanade.tachiyomi.ui.library.LibraryController import eu.kanade.tachiyomi.ui.setting.SettingsLibraryController import eu.kanade.tachiyomi.util.view.compatToolTipText import eu.kanade.tachiyomi.util.view.withFadeTransaction import eu.kanade.tachiyomi.widget.TabbedBottomSheetDialog -import uy.kohesive.injekt.Injekt -import uy.kohesive.injekt.api.get open class TabbedLibraryDisplaySheet(val controller: Controller) : TabbedBottomSheetDialog(controller.activity!!) { @@ -43,21 +39,15 @@ open class TabbedLibraryDisplaySheet(val controller: Controller) : } if (controller is LibraryController) { - setExpandText( - !controller.singleCategory && controller.presenter.showAllCategories, - Injekt.get().collapsedCategories().getOrDefault().isNotEmpty(), - false - ) + setExpandText(controller.canCollapseOrExpandCategory(), false) } else { - setExpandText(showExpanded = false, allExpanded = false) + setExpandText(null) categoryView.binding.addCategoriesButton.isVisible = false } } - fun setExpandText(showExpanded: Boolean, allExpanded: Boolean, animated: Boolean = true) { - categoryView.showExpandCategories(showExpanded) + fun setExpandText(allExpanded: Boolean?, animated: Boolean = true) = categoryView.setExpandText(allExpanded, animated) - } override fun dismiss() { super.dismiss()