From d9ad6895067fc644c80604de1164c0547443cf7c Mon Sep 17 00:00:00 2001 From: Jay Date: Sun, 17 May 2020 02:15:24 -0400 Subject: [PATCH] Optimizations to sorting + category refactoring MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Category: • new bool called isDynamic used for all category • new bool called isAlone, for when using no categories or when hiding all categories Sort Optimizing: •Using SQLite query for library mangas to also set the total chapters, instead of checking the total count later •No longer using regex for removing articles from text, because it's pretty heavy •All category now uses the same catergory sorting logic as regular categories --- .../data/database/models/Category.kt | 23 +- .../data/database/models/CategoryImpl.kt | 6 +- .../data/database/models/LibraryManga.kt | 7 +- .../resolvers/LibraryMangaGetResolver.kt | 2 +- .../ui/library/LibraryCategoryAdapter.kt | 2 +- .../tachiyomi/ui/library/LibraryController.kt | 3 +- .../tachiyomi/ui/library/LibraryHeaderItem.kt | 9 +- .../tachiyomi/ui/library/LibraryHolder.kt | 5 +- .../tachiyomi/ui/library/LibraryItem.kt | 1 - .../tachiyomi/ui/library/LibraryPresenter.kt | 228 +++++++----------- .../tachiyomi/util/lang/StringExtensions.kt | 7 +- 11 files changed, 122 insertions(+), 171 deletions(-) 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 3fbecd9112..73ff8d1f6c 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 @@ -19,14 +19,15 @@ interface Category : Serializable { var mangaSort: Char? - var isFirst: Boolean? - var isLast: Boolean? + var isAlone: Boolean val nameLower: String get() = name.toLowerCase() var isHidden: Boolean + var isDynamic: Boolean + fun isAscending(): Boolean { return ((mangaSort?.minus('a') ?: 0) % 2) != 1 } @@ -49,7 +50,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 -> if (id == -1) R.string.category else R.string.drag_and_drop + else -> if (isDynamic) R.string.category else R.string.drag_and_drop } fun catSortingMode(): Int? = when (mangaSort) { @@ -96,12 +97,10 @@ interface Category : Serializable { fun createDefault(context: Context): Category = create(context.getString(R.string.default_value)).apply { id = 0 - isFirst = true } - fun createAll(context: Context, libSort: Int, ascending: Boolean): Category = - create(context.getString(R.string.all)).apply { - id = -1 + fun createCustom(name: String, libSort: Int, ascending: Boolean): Category = + create(name).apply { mangaSort = when (libSort) { LibrarySort.ALPHA -> ALPHA_ASC LibrarySort.LATEST_CHAPTER -> UPDATED_ASC @@ -113,11 +112,15 @@ interface Category : Serializable { else -> DRAG_AND_DROP } if (mangaSort != DRAG_AND_DROP && !ascending) { - mangaSort?.plus(1) + mangaSort = mangaSort?.plus(1) } + isDynamic = true + } + + fun createAll(context: Context, libSort: Int, ascending: Boolean): Category = + createCustom(context.getString(R.string.all), libSort, ascending).apply { + id = -1 order = -1 - isFirst = true - isLast = true } } } 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 ad5921b977..6b27e0eee8 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 @@ -14,12 +14,12 @@ class CategoryImpl : Category { override var mangaSort: Char? = null - override var isFirst: Boolean? = null - - override var isLast: Boolean? = null + override var isAlone: Boolean = false override var isHidden: Boolean = false + override var isDynamic: 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 1297c28b10..d6cdd4a2cc 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 @@ -3,10 +3,15 @@ package eu.kanade.tachiyomi.data.database.models class LibraryManga : MangaImpl() { var unread: Int = 0 + var read: Int = 0 var category: Int = 0 - var hasRead: Boolean = false + val totalChapters + get() = read + unread + + val hasRead + get() = read > 0 companion object { fun createBlank(categoryId: Int): LibraryManga = LibraryManga().apply { diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/LibraryMangaGetResolver.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/LibraryMangaGetResolver.kt index e70e19ada4..f3113d8681 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/LibraryMangaGetResolver.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/LibraryMangaGetResolver.kt @@ -18,7 +18,7 @@ class LibraryMangaGetResolver : DefaultGetResolver(), BaseMangaGet mapBaseFromCursor(manga, cursor) manga.unread = cursor.getInt(cursor.getColumnIndex(MangaTable.COL_UNREAD)) manga.category = cursor.getInt(cursor.getColumnIndex(MangaTable.COL_CATEGORY)) - manga.hasRead = cursor.getInt(cursor.getColumnIndex(MangaTable.COL_HAS_READ)) > 0 + manga.read = cursor.getInt(cursor.getColumnIndex(MangaTable.COL_HAS_READ)) return manga } 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 e81bade047..d0e3ed7d77 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 @@ -155,7 +155,7 @@ class LibraryCategoryAdapter(val controller: LibraryController) : else recyclerView.context.getString(R.string.read) } LibrarySort.TOTAL -> { - val total = item.chapterCount + val total = item.manga.totalChapters if (total > 0) recyclerView.resources.getQuantityString( R.plurals.chapters, total, total ) 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 bb8fa623ba..f7a3d44d3a 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 @@ -1109,8 +1109,9 @@ class LibraryController( override fun manageCategory(position: Int) { val category = (adapter.getItem(position) as? LibraryHeaderItem)?.category ?: return - if (category.id ?: 0 > -1) + if (!category.isDynamic) { ManageCategoryDialog(this, category).showDialog(router) + } } override fun sortCategory(catId: Int, sortBy: Int) { 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 47b58f3f3a..8a5e83fdf8 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 @@ -143,7 +143,7 @@ class LibraryHeaderItem( } val category = item.category - if (category.isFirst == true && category.isLast == true) sectionText.text = "" + if (category.isAlone) sectionText.text = "" else sectionText.text = category.name sortText.text = itemView.context.getString( R.string.sort_by_, itemView.context.getString(category.sortRes()) @@ -165,14 +165,15 @@ class LibraryHeaderItem( when { adapter.mode == SelectableAdapter.Mode.MULTI -> { checkboxImage.visibleIf(!category.isHidden) - expandImage.visibleIf(category.isHidden && !adapter.isSingleCategory) + expandImage.visibleIf(category.isHidden && !adapter.isSingleCategory && !category.isDynamic) updateButton.gone() catProgress.gone() setSelection() } - category.id == -1 -> { + category.isDynamic -> { expandImage.gone() checkboxImage.gone() + catProgress.gone() updateButton.gone() } LibraryUpdateService.categoryInQueue(category.id) -> { @@ -185,7 +186,7 @@ class LibraryHeaderItem( expandImage.visibleIf(!adapter.isSingleCategory) catProgress.gone() checkboxImage.gone() - updateButton.visibleIf(category.id ?: 0 > -1 && !adapter.isSingleCategory) + updateButton.visibleIf(!adapter.isSingleCategory) } } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryHolder.kt index 8f87fcfa2c..c5f3b41c6c 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryHolder.kt @@ -26,9 +26,10 @@ abstract class LibraryHolder( abstract fun onSetValues(item: LibraryItem) fun setUnreadBadge(badge: LibraryBadge, item: LibraryItem) { + val showTotal = item.header.category.sortingMode() == LibrarySort.TOTAL badge.setUnreadDownload( when { - item.chapterCount > -1 -> item.chapterCount + showTotal -> item.manga.totalChapters item.unreadType == 2 -> item.manga.unread item.unreadType == 1 -> if (item.manga.unread > 0) -1 else -2 else -> -2 @@ -38,7 +39,7 @@ abstract class LibraryHolder( item.manga.source == LocalSource.ID -> -2 else -> item.downloadCount }, - item.chapterCount > -1) + showTotal) } fun setReadingButton(item: LibraryItem) { 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 54489a9e33..3cf00fb545 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 @@ -35,7 +35,6 @@ class LibraryItem( var downloadCount = -1 var unreadType = 2 - var chapterCount = -1 private val uniformSize: Boolean get() = preferences.uniformGrid().getOrDefault() 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 69caea4e8d..cf56ad33d2 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 @@ -54,6 +54,10 @@ class LibraryPresenter( var categories: List = emptyList() private set + var hashCategories: HashMap = hashMapOf() + + var removeArticles: Boolean = preferences.removeArticles().getOrDefault() + /** All categories of the library, in case they are hidden because of hide categories is on */ var allCategories: List = emptyList() private set @@ -67,8 +71,6 @@ class LibraryPresenter( val showAllCategories get() = preferences.showAllCategories().get() - private var totalChapters: Map? = null - /** Save the current list to speed up loading later */ fun onDestroy() { lastLibraryItems = libraryItems @@ -86,7 +88,6 @@ class LibraryPresenter( /** Get favorited manga for library and sort and filter it */ fun getLibrary() { scope.launch { - totalChapters = null val library = withContext(Dispatchers.IO) { getLibraryFromDB() } library.apply { setDownloadCount(library) @@ -98,9 +99,6 @@ class LibraryPresenter( mangaMap = applySort(mangaMap) val freshStart = libraryItems.isEmpty() sectionLibrary(mangaMap, freshStart) - withContext(Dispatchers.IO) { - setTotalChapters() - } } } @@ -313,74 +311,81 @@ class LibraryPresenter( * @param itemList the map to sort. */ private fun applySort(itemList: List): List { - val sortingMode = preferences.librarySortingMode().getOrDefault() - val lastReadManga by lazy { var counter = 0 db.getLastReadManga().executeAsBlocking().associate { it.id!! to counter++ } } - val ascending = preferences.librarySortingAscending().getOrDefault() - val useDnD = !preferences.hideCategories().getOrDefault() - val sortFn: (LibraryItem, LibraryItem) -> Int = { i1, i2 -> - if (!(sortingMode == LibrarySort.DRAG_AND_DROP || useDnD)) { - i1.chapterCount = -1 - i2.chapterCount = -1 - } - val compare = when { - sortingMode == LibrarySort.DRAG_AND_DROP || useDnD -> - sortCategory(i1, i2, lastReadManga) - sortingMode == LibrarySort.ALPHA -> sortAlphabetical(i1, i2) - sortingMode == LibrarySort.LAST_READ -> { - // Get index of manga, set equal to list if size unknown. - val manga1LastRead = lastReadManga[i1.manga.id!!] ?: lastReadManga.size - val manga2LastRead = lastReadManga[i2.manga.id!!] ?: lastReadManga.size - manga1LastRead.compareTo(manga2LastRead) + if (i1.header.category.id == i2.header.category.id) { + val category = i1.header.category + if (category.mangaOrder.isNullOrEmpty() && category.mangaSort == null) { + category.changeSortTo(preferences.librarySortingMode().getOrDefault()) + if (category.id == 0) preferences.defaultMangaOrder() + .set(category.mangaSort.toString()) + else if (!category.isDynamic) db.insertCategory(category).executeAsBlocking() } - sortingMode == LibrarySort.LATEST_CHAPTER -> i2.manga.last_update.compareTo(i1 - .manga.last_update) - sortingMode == LibrarySort.UNREAD -> - when { - i1.manga.unread == i2.manga.unread -> 0 - i1.manga.unread == 0 -> if (ascending) 1 else -1 - i2.manga.unread == 0 -> if (ascending) -1 else 1 - else -> i1.manga.unread.compareTo(i2.manga.unread) + val compare = when { + category.mangaSort != null -> { + var sort = when (category.sortingMode()) { + LibrarySort.ALPHA -> sortAlphabetical(i1, i2) + LibrarySort.LATEST_CHAPTER -> i2.manga.last_update.compareTo(i1.manga.last_update) + LibrarySort.UNREAD -> when { + i1.manga.unread == i2.manga.unread -> 0 + i1.manga.unread == 0 -> if (category.isAscending()) 1 else -1 + i2.manga.unread == 0 -> if (category.isAscending()) -1 else 1 + else -> i1.manga.unread.compareTo(i2.manga.unread) + } + LibrarySort.LAST_READ -> { + val manga1LastRead = lastReadManga[i1.manga.id!!] ?: lastReadManga.size + val manga2LastRead = lastReadManga[i2.manga.id!!] ?: lastReadManga.size + manga1LastRead.compareTo(manga2LastRead) + } + LibrarySort.TOTAL -> { + i1.manga.totalChapters.compareTo(i2.manga.totalChapters) + } + LibrarySort.DATE_ADDED -> i2.manga.date_added.compareTo(i1.manga.date_added) + else -> { + if (LibrarySort.DRAG_AND_DROP == category.sortingMode() && category.isDynamic) { + val category1 = + allCategories.find { i1.manga.category == it.id }?.order + ?: 0 + val category2 = + allCategories.find { i2.manga.category == it.id }?.order + ?: 0 + category1.compareTo(category2) + } else { + sortAlphabetical(i1, i2) + } + } + } + if (!category.isAscending()) sort *= -1 + sort } - sortingMode == LibrarySort.TOTAL -> { - setTotalChapters() - val manga1TotalChapter = totalChapters!![i1.manga.id!!] ?: 0 - val mange2TotalChapter = totalChapters!![i2.manga.id!!] ?: 0 - i1.chapterCount = totalChapters!![i1.manga.id!!] ?: 0 - i2.chapterCount = totalChapters!![i2.manga.id!!] ?: 0 - manga1TotalChapter.compareTo(mange2TotalChapter) + category.mangaOrder.isNotEmpty() -> { + val order = category.mangaOrder + val index1 = order.indexOf(i1.manga.id!!) + val index2 = order.indexOf(i2.manga.id!!) + when { + index1 == index2 -> 0 + index1 == -1 -> -1 + index2 == -1 -> 1 + else -> index1.compareTo(index2) + } + } + else -> 0 } - sortingMode == LibrarySort.DATE_ADDED -> { - i2.manga.date_added.compareTo(i1.manga.date_added) - } - else -> 0 + if (compare == 0) { + sortAlphabetical(i1, i2) + } else compare + } else { + val category = i1.header.category.order + val category2 = i2.header.category.order + category.compareTo(category2) } - if (!(sortingMode == LibrarySort.DRAG_AND_DROP || useDnD) && compare == 0) { - if (ascending) sortAlphabetical(i1, i2) - else sortAlphabetical(i2, i1) - } else compare } - val comparator = if (ascending || useDnD) - Comparator(sortFn) - else - Collections.reverseOrder(sortFn) - - return itemList.sortedWith(comparator) - } - - /** Set the total chapters for the manga in the library */ - private fun setTotalChapters() { - if (totalChapters != null) return - val mangaMap = allLibraryItems - totalChapters = mangaMap.map { - it.manga.id!! to db.getChapters(it.manga).executeAsBlocking().size - }.toMap() + return itemList.sortedWith(Comparator(sortFn)) } /** Gets the category by id @@ -388,89 +393,11 @@ class LibraryPresenter( * @param categoryId id of the categoty to get */ private fun getCategory(categoryId: Int): Category { - val category = categories.find { it.id == categoryId } ?: createDefaultCategory() - if (category.isFirst == null) { - category.isFirst = categories.minBy { it.order }?.id == category.id - } - if (category.isLast == null) category.isLast = categories.lastOrNull()?.id == category.id + val category = hashCategories[categoryId] ?: createDefaultCategory() + category.isAlone = categories.size <= 1 return category } - /** - * Sort 2 manga by the category's sorting - * - * @param i1 the first manga - * @param i2 the second manga to compare - * @param lastReadManga map of the last read of the library - */ - private fun sortCategory( - i1: LibraryItem, - i2: LibraryItem, - lastReadManga: Map - ): Int { - return if (i1.header.category.id == i2.header.category.id) { - val category = i1.header.category - if (category.mangaOrder.isNullOrEmpty() && category.mangaSort == null) { - category.changeSortTo(preferences.librarySortingMode().getOrDefault()) - if (category.id == 0) preferences.defaultMangaOrder() - .set(category.mangaSort.toString()) - else if (category.id ?: 0 > 0) db.insertCategory(category).executeAsBlocking() - } - i1.chapterCount = -1 - i2.chapterCount = -1 - val compare = when { - category.mangaSort != null -> { - var sort = when (category.sortingMode()) { - LibrarySort.ALPHA -> sortAlphabetical(i1, i2) - LibrarySort.LATEST_CHAPTER -> i2.manga.last_update.compareTo(i1.manga.last_update) - LibrarySort.UNREAD -> when { - i1.manga.unread == i2.manga.unread -> 0 - i1.manga.unread == 0 -> if (category.isAscending()) 1 else -1 - i2.manga.unread == 0 -> if (category.isAscending()) -1 else 1 - else -> i1.manga.unread.compareTo(i2.manga.unread) - } - LibrarySort.LAST_READ -> { - val manga1LastRead = lastReadManga[i1.manga.id!!] ?: lastReadManga.size - val manga2LastRead = lastReadManga[i2.manga.id!!] ?: lastReadManga.size - manga1LastRead.compareTo(manga2LastRead) - } - LibrarySort.TOTAL -> { - setTotalChapters() - val manga1TotalChapter = totalChapters!![i1.manga.id!!] ?: 0 - val mange2TotalChapter = totalChapters!![i2.manga.id!!] ?: 0 - i1.chapterCount = totalChapters!![i1.manga.id!!] ?: 0 - i2.chapterCount = totalChapters!![i2.manga.id!!] ?: 0 - manga1TotalChapter.compareTo(mange2TotalChapter) - } - LibrarySort.DATE_ADDED -> i2.manga.date_added.compareTo(i1.manga.date_added) - else -> sortAlphabetical(i1, i2) - } - if (!category.isAscending()) sort *= -1 - sort - } - category.mangaOrder.isNotEmpty() -> { - val order = category.mangaOrder - val index1 = order.indexOf(i1.manga.id!!) - val index2 = order.indexOf(i2.manga.id!!) - when { - index1 == index2 -> 0 - index1 == -1 -> -1 - index2 == -1 -> 1 - else -> index1.compareTo(index2) - } - } - else -> 0 - } - if (compare == 0) { - sortAlphabetical(i1, i2) - } else compare - } else { - val category = i1.header.category.order - val category2 = i2.header.category.order - category.compareTo(category2) - } - } - /** * Sort 2 manga by the their title (and remove articles if need be) * @@ -478,9 +405,11 @@ class LibraryPresenter( * @param i2 the second manga to compare */ private fun sortAlphabetical(i1: LibraryItem, i2: LibraryItem): Int { - return if (preferences.removeArticles().getOrDefault()) + return if (removeArticles) { i1.manga.title.removeArticles().compareTo(i2.manga.title.removeArticles(), true) - else i1.manga.title.compareTo(i2.manga.title, true) + } else { + i1.manga.title.compareTo(i2.manga.title, true) + } } /** @@ -489,6 +418,7 @@ class LibraryPresenter( * @return an list of all the manga in a itemized form. */ private fun getLibraryFromDB(): List { + removeArticles = preferences.removeArticles().getOrDefault() val categories = db.getCategories().executeAsBlocking().toMutableList() val showCategories = !preferences.hideCategories().getOrDefault() var libraryManga = db.getLibraryMangas().executeAsBlocking() @@ -550,6 +480,10 @@ class LibraryPresenter( this.categories = if (!showCategories) arrayListOf(categoryAll) else categories + hashCategories = HashMap(this.categories.mapNotNull { + it.id!! to it + }.toMap()) + return items } @@ -694,7 +628,7 @@ class LibraryPresenter( fun sortCategory(catId: Int, order: Int) { val category = categories.find { catId == it.id } ?: return category.mangaSort = ('a' + (order - 1)) - if (catId == -1) { + if (catId == -1 || category.isDynamic) { val sort = category.sortingMode() ?: LibrarySort.ALPHA preferences.librarySortingMode().set(sort) preferences.librarySortingAscending().set(category.isAscending()) @@ -709,6 +643,7 @@ class LibraryPresenter( fun rearrangeCategory(catId: Int?, mangaIds: List) { scope.launch { val category = categories.find { catId == it.id } ?: return@launch + if (category.isDynamic) return@launch category.mangaSort = null category.mangaOrder = mangaIds if (category.id == 0) preferences.defaultMangaOrder().set(mangaIds.joinToString("/")) @@ -726,6 +661,7 @@ class LibraryPresenter( scope.launch { val categoryId = catId ?: return@launch val category = categories.find { catId == it.id } ?: return@launch + if (category.isDynamic) return@launch val oldCatId = manga.category manga.category = categoryId @@ -762,7 +698,7 @@ class LibraryPresenter( } fun toggleCategoryVisibility(categoryId: Int) { - if (categoryId <= -1) return + if (categoryId <= -1 || categories.find { it.id == categoryId }?.isDynamic == true) return val categoriesHidden = preferences.collapsedCategories().getOrDefault().mapNotNull { it.toIntOrNull() }.toMutableSet() diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/lang/StringExtensions.kt b/app/src/main/java/eu/kanade/tachiyomi/util/lang/StringExtensions.kt index bbbff6aa13..52a6713fff 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/util/lang/StringExtensions.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/util/lang/StringExtensions.kt @@ -14,7 +14,12 @@ fun String.chop(count: Int, replacement: String = "..."): String { } fun String.removeArticles(): String { - return this.replace(Regex("^(an|a|the) ", RegexOption.IGNORE_CASE), "") + return when { + startsWith("a ", true) -> substring(2) + startsWith("an ", true) -> substring(3) + startsWith("the ", true) -> substring(4) + else -> this + } } /**