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 632ce67bf7..3fbecd9112 100644 --- 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 @@ -25,6 +25,8 @@ interface Category : Serializable { val nameLower: String get() = name.toLowerCase() + var isHidden: Boolean + fun isAscending(): Boolean { return ((mangaSort?.minus('a') ?: 0) % 2) != 1 } @@ -47,7 +49,7 @@ interface Category : Serializable { LAST_READ_ASC, LAST_READ_DSC -> R.string.last_read TOTAL_ASC, TOTAL_DSC -> R.string.total_chapters DATE_ADDED_ASC, DATE_ADDED_DSC -> R.string.date_added - else -> R.string.drag_and_drop + else -> if (id == -1) R.string.category else R.string.drag_and_drop } fun catSortingMode(): Int? = when (mangaSort) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/database/models/CategoryImpl.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/models/CategoryImpl.kt index 1332434efe..ad5921b977 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/models/CategoryImpl.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/database/models/CategoryImpl.kt @@ -18,6 +18,8 @@ class CategoryImpl : Category { override var isLast: Boolean? = null + override var isHidden: Boolean = false + override fun equals(other: Any?): Boolean { if (this === other) return true if (other == null || javaClass != other.javaClass) return false diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/database/models/LibraryManga.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/models/LibraryManga.kt index 31523a7b51..5bd127e7bf 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/models/LibraryManga.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/database/models/LibraryManga.kt @@ -14,5 +14,9 @@ class LibraryManga : MangaImpl() { id = Long.MIN_VALUE category = categoryId } + + fun createHide(categoryId: Int): LibraryManga = createBlank(categoryId).apply { + status = -1 + } } } 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 1ddd54b2db..87364767b0 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt @@ -51,10 +51,6 @@ object PreferenceKeys { const val readWithVolumeKeysInverted = "reader_volume_keys_inverted" - const val portraitColumns = "pref_library_columns_portrait_key" - - const val landscapeColumns = "pref_library_columns_landscape_key" - const val updateOnlyNonCompleted = "pref_update_only_non_completed_key" const val autoUpdateTrack = "pref_auto_update_manga_sync_key" 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 29282ba4cd..9d133a9917 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 @@ -103,10 +103,6 @@ class PreferencesHelper(val context: Context) { fun readWithVolumeKeysInverted() = rxPrefs.getBoolean(Keys.readWithVolumeKeysInverted, false) - fun portraitColumns() = rxPrefs.getInteger(Keys.portraitColumns, 0) - - fun landscapeColumns() = rxPrefs.getInteger(Keys.landscapeColumns, 0) - fun updateOnlyNonCompleted() = prefs.getBoolean(Keys.updateOnlyNonCompleted, false) fun autoUpdateTrack() = prefs.getBoolean(Keys.autoUpdateTrack, true) @@ -205,6 +201,8 @@ class PreferencesHelper(val context: Context) { fun automaticExtUpdates() = rxPrefs.getBoolean(Keys.automaticExtUpdates, false) + fun collapsedCategories() = rxPrefs.getStringSet("collapsed_categories", mutableSetOf()) + fun hiddenCatalogues() = rxPrefs.getStringSet("hidden_catalogues", mutableSetOf()) fun downloadNew() = rxPrefs.getBoolean(Keys.downloadNew, false) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryAdapter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryAdapter.kt index c039945425..20195156d1 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryAdapter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCategoryAdapter.kt @@ -153,7 +153,7 @@ class LibraryCategoryAdapter(val libraryListener: LibraryListener) : } private fun getFirstLetter(name: String): String { - val letter = name.first() + val letter = name.firstOrNull() ?: '#' return if (letter.isLetter()) letter.toString() .toUpperCase(Locale.ROOT) else "#" } @@ -272,5 +272,6 @@ class LibraryCategoryAdapter(val libraryListener: LibraryListener) : fun sortCategory(catId: Int, sortBy: Int) fun selectAll(position: Int) fun allSelected(position: Int): Boolean + fun toggleCategoryVisibility(position: Int) } } 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 26d2df1b9e..a583e2edbc 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 @@ -804,6 +804,11 @@ class LibraryController( return true } + override fun toggleCategoryVisibility(position: Int) { + val catId = (adapter.getItem(position) as? LibraryHeaderItem)?.category?.id ?: return + presenter.toggleCategoryVisibility(catId) + } + override fun sortCategory(catId: Int, sortBy: Int) { presenter.sortCategory(catId, sortBy) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryHeaderItem.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryHeaderItem.kt index 8d985b2440..8c0a54248d 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryHeaderItem.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryHeaderItem.kt @@ -18,11 +18,11 @@ import eu.davidea.flexibleadapter.FlexibleAdapter import eu.davidea.flexibleadapter.SelectableAdapter import eu.davidea.flexibleadapter.items.AbstractHeaderItem import eu.davidea.flexibleadapter.items.IFlexible -import eu.davidea.viewholders.FlexibleViewHolder import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.database.models.Category import eu.kanade.tachiyomi.data.library.LibraryUpdateService import eu.kanade.tachiyomi.data.preference.getOrDefault +import eu.kanade.tachiyomi.ui.base.holder.BaseFlexibleViewHolder import eu.kanade.tachiyomi.util.system.dpToPx import eu.kanade.tachiyomi.util.system.getResourceColor import eu.kanade.tachiyomi.util.view.gone @@ -30,7 +30,6 @@ import eu.kanade.tachiyomi.util.view.invisible import eu.kanade.tachiyomi.util.view.updateLayoutParams import eu.kanade.tachiyomi.util.view.visInvisIf import eu.kanade.tachiyomi.util.view.visible -import kotlinx.android.synthetic.main.library_category_header_item.view.* class LibraryHeaderItem( private val categoryF: (Int) -> Category, @@ -83,7 +82,7 @@ class LibraryHeaderItem( } class Holder(val view: View, private val adapter: LibraryCategoryAdapter, padEnd: Boolean) : - FlexibleViewHolder(view, adapter, true) { + BaseFlexibleViewHolder(view, adapter, true) { private val sectionText: TextView = view.findViewById(R.id.category_title) private val sortText: TextView = view.findViewById(R.id.category_sort) @@ -96,6 +95,10 @@ class LibraryHeaderItem( marginEnd = (if (padEnd && adapter.recyclerView.paddingEnd == 0) 12 else 2).dpToPx } updateButton.setOnClickListener { addCategoryToUpdate() } + sectionText.setOnLongClickListener { + adapter.libraryListener.toggleCategoryVisibility(adapterPosition) + true + } sortText.setOnClickListener { it.post { showCatSortOptions() } } checkboxImage.setOnClickListener { selectAll() } updateButton.drawable.mutate() @@ -109,20 +112,25 @@ class LibraryHeaderItem( if (category.isFirst == true && category.isLast == true) sectionText.text = "" else sectionText.text = category.name sortText.text = itemView.context.getString(R.string.sort_by_, - itemView.context.getString( - when (category.sortingMode()) { - LibrarySort.LATEST_CHAPTER -> R.string.latest_chapter - LibrarySort.DRAG_AND_DROP -> - if (category.id == -1) R.string.category - else R.string.drag_and_drop - LibrarySort.TOTAL -> R.string.total_chapters - LibrarySort.UNREAD -> R.string.unread - LibrarySort.LAST_READ -> R.string.last_read - LibrarySort.ALPHA -> R.string.title - LibrarySort.DATE_ADDED -> R.string.date_added - else -> R.string.drag_and_drop + itemView.context.getString(category.sortRes()) + ) + + val isAscending = category.isAscending() + val sortingMode = category.sortingMode() + val sortDrawable = if (category.isHidden) R.drawable.ic_expand_more_white_24dp + else + when { + sortingMode == LibrarySort.DRAG_AND_DROP || sortingMode == null -> R.drawable + .ic_sort_white_24dp + if (sortingMode == LibrarySort.DATE_ADDED || + sortingMode == LibrarySort.LATEST_CHAPTER || + sortingMode == LibrarySort.LAST_READ) !isAscending else isAscending -> + R.drawable.ic_arrow_down_white_24dp + else -> R.drawable.ic_arrow_up_white_24dp } - )) + + sortText.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, sortDrawable, 0) + sortText.setText(if (category.isHidden) R.string.collasped else category.sortRes()) when { adapter.mode == SelectableAdapter.Mode.MULTI -> { @@ -157,8 +165,12 @@ class LibraryHeaderItem( private fun showCatSortOptions() { val category = (adapter.getItem(adapterPosition) as? LibraryHeaderItem)?.category ?: return + if (category.isHidden) { + adapter.libraryListener.toggleCategoryVisibility(adapterPosition) + return + } // Create a PopupMenu, giving it the clicked view for an anchor - val popup = PopupMenu(itemView.context, view.category_sort) + val popup = PopupMenu(itemView.context, sortText) // Inflate our menu resource into the PopupMenu's Menu popup.menuInflater.inflate( @@ -254,14 +266,17 @@ class LibraryHeaderItem( fun setSelection() { val allSelected = adapter.libraryListener.allSelected(adapterPosition) - val drawable = - ContextCompat.getDrawable(contentView.context, - if (allSelected) R.drawable.ic_check_circle_white_24dp else - R.drawable.ic_radio_button_unchecked_white_24dp) + val drawable = ContextCompat.getDrawable( + contentView.context, + if (allSelected) R.drawable.ic_check_circle_white_24dp else R.drawable.ic_radio_button_unchecked_white_24dp + ) val tintedDrawable = drawable?.mutate() - tintedDrawable?.setTint(ContextCompat.getColor(contentView.context, - if (allSelected) R.color.colorAccent - else R.color.gray_button)) + tintedDrawable?.setTint( + ContextCompat.getColor( + contentView.context, if (allSelected) R.color.colorAccent + else R.color.gray_button + ) + ) checkboxImage.setImageDrawable(tintedDrawable) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryListHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryListHolder.kt index a09885e373..6c9b0408a8 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryListHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryListHolder.kt @@ -46,13 +46,23 @@ class LibraryListHolder( */ override fun onSetValues(item: LibraryItem) { + title.visible() + constraint_layout.minHeight = 56.dpToPx if (item.manga.isBlank()) { - title.text = itemView.context.getString(R.string.category_is_empty) + constraint_layout.minHeight = 0 + if (item.manga.status == -1) { + title.gone() + } else + title.text = itemView.context.getString(R.string.category_is_empty) title.textAlignment = View.TEXT_ALIGNMENT_CENTER card.gone() badge_view.gone() + play_layout.gone() + padding.gone() + subtitle.gone() return } + padding.visible() card.visible() title.textAlignment = View.TEXT_ALIGNMENT_TEXT_START 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 64ffa4ea46..275d216d04 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 @@ -425,12 +425,27 @@ class LibraryPresenter( LibraryItem(it, libraryLayout, preferences.uniformGrid(), seekPref, headerItem) }.toMutableList() + val categoriesHidden = preferences.collapsedCategories().getOrDefault().mapNotNull { + it.toIntOrNull() + }.toMutableSet() + if (showCategories) { categories.forEach { category -> - if (category.id ?: 0 <= 0 && !categorySet.contains(category.id)) { - val headerItem = headerItems[category.id ?: 0] + val catId = category.id ?: return@forEach + if (catId > 0 && !categorySet.contains(catId)) { + val headerItem = headerItems[catId] items.add(LibraryItem( - LibraryManga.createBlank(category.id!!), + LibraryManga.createBlank(catId), + libraryLayout, + preferences.uniformGrid(), + preferences.alwaysShowSeeker(), + headerItem + )) + } else if (catId in categoriesHidden) { + val headerItem = headerItems[catId] + items.removeAll { it.manga.category == catId } + items.add(LibraryItem( + LibraryManga.createHide(catId), libraryLayout, preferences.uniformGrid(), preferences.alwaysShowSeeker(), @@ -446,6 +461,10 @@ class LibraryPresenter( if (categorySet.contains(0)) categories.add(0, createDefaultCategory()) + categories.forEach { + it.isHidden = it.id in categoriesHidden + } + this.allCategories = categories this.categories = if (!showCategories) arrayListOf(categoryAll) else categories @@ -678,7 +697,21 @@ class LibraryPresenter( return catId in categories } + fun toggleCategoryVisibility(categoryId: Int) { + if (categoryId <= -1) return + 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()) + getLibrary() + } + companion object { + // var catsHidden = mutableListOf() private var lastLibraryItems: List? = null private var lastCategories: List? = null diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaDetailsPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaDetailsPresenter.kt index 54345c0dc8..c826f62ad8 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaDetailsPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaDetailsPresenter.kt @@ -521,7 +521,7 @@ class MangaDetailsPresenter( asyncUpdateMangaAndChapters() } - fun globalSort() = preferences.chaptersDescAsDefault().getOrDefault() + fun globalSort(): Boolean = preferences.chaptersDescAsDefault().getOrDefault() fun setGlobalChapterSort(descend: Boolean) { preferences.chaptersDescAsDefault().set(descend) diff --git a/app/src/main/res/drawable/square_ripple.xml b/app/src/main/res/drawable/square_ripple.xml index 6effa62ed9..3d0357453f 100644 --- a/app/src/main/res/drawable/square_ripple.xml +++ b/app/src/main/res/drawable/square_ripple.xml @@ -4,7 +4,7 @@ - + \ No newline at end of file diff --git a/app/src/main/res/layout/catalogue_list_item.xml b/app/src/main/res/layout/catalogue_list_item.xml index 7d764b1068..e31c86213f 100644 --- a/app/src/main/res/layout/catalogue_list_item.xml +++ b/app/src/main/res/layout/catalogue_list_item.xml @@ -5,6 +5,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center_vertical" + android:id="@+id/constraint_layout" android:background="?attr/selectable_list_drawable" android:minHeight="@dimen/material_component_lists_single_line_with_avatar_height"> diff --git a/app/src/main/res/layout/library_category_header_item.xml b/app/src/main/res/layout/library_category_header_item.xml index 9a84520729..1b74b6ec90 100644 --- a/app/src/main/res/layout/library_category_header_item.xml +++ b/app/src/main/res/layout/library_category_header_item.xml @@ -6,25 +6,23 @@ android:layout_height="wrap_content" android:gravity="center_vertical"> - + tools:tint="?attr/colorAccent" + tools:visibility="visible" /> + app:layout_constraintTop_toTopOf="@id/update_button" + tools:visibility="visible" /> \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 9a8d50c286..31fbe177d7 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -66,6 +66,7 @@ %1$s is already in queue Create new category Category is empty + Category is hidden Top category (%1$s) Default category First category @@ -600,6 +601,7 @@ Charging Clear Close + Collapsed Common Cover of manga Create @@ -637,6 +639,8 @@ Options Pause Picture saved + Refresh + Refreshing Remove Reorder Reset @@ -656,6 +660,7 @@ Top Undo Unknown error + Un-select all Use default View all errors View chapters diff --git a/captures/eu.kanade.tachiyomi.debug_2020.04.16_14.54.li b/captures/eu.kanade.tachiyomi.debug_2020.04.16_14.54.li new file mode 100644 index 0000000000..9c979c8096 Binary files /dev/null and b/captures/eu.kanade.tachiyomi.debug_2020.04.16_14.54.li differ