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 ab819754b0..09f00c37d5 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 @@ -69,6 +69,7 @@ import eu.kanade.tachiyomi.ui.base.MaterialMenuSheet import eu.kanade.tachiyomi.ui.base.controller.BaseCoroutineController import eu.kanade.tachiyomi.ui.category.CategoryController import eu.kanade.tachiyomi.ui.category.ManageCategoryDialog +import eu.kanade.tachiyomi.ui.library.LibraryGroup.BY_AUTHOR import eu.kanade.tachiyomi.ui.library.LibraryGroup.BY_DEFAULT import eu.kanade.tachiyomi.ui.library.LibraryGroup.BY_SOURCE import eu.kanade.tachiyomi.ui.library.LibraryGroup.BY_STATUS @@ -494,7 +495,7 @@ class LibraryController( } private fun showGroupOptions() { - val groupItems = mutableListOf(BY_DEFAULT, BY_TAG, BY_SOURCE, BY_STATUS) + val groupItems = mutableListOf(BY_DEFAULT, BY_TAG, BY_SOURCE, BY_STATUS, BY_AUTHOR) if (presenter.isLoggedIntoTracking) { groupItems.add(BY_TRACK_STATUS) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryGroup.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryGroup.kt index c033e4a236..143b0b2704 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryGroup.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryGroup.kt @@ -9,6 +9,7 @@ object LibraryGroup { const val BY_SOURCE = 2 const val BY_STATUS = 3 const val BY_TRACK_STATUS = 4 + const val BY_AUTHOR = 6 const val UNGROUPED = 5 fun groupTypeStringRes(type: Int, hasCategories: Boolean = true): Int { @@ -17,6 +18,7 @@ object LibraryGroup { BY_TAG -> R.string.tag BY_SOURCE -> R.string.sources BY_TRACK_STATUS -> R.string.tracking_status + BY_AUTHOR -> R.string.author UNGROUPED -> R.string.ungrouped else -> if (hasCategories) R.string.categories else R.string.ungrouped } @@ -28,6 +30,7 @@ object LibraryGroup { BY_TAG -> R.drawable.ic_style_24dp BY_TRACK_STATUS -> R.drawable.ic_sync_24dp BY_SOURCE -> R.drawable.ic_browse_24dp + BY_AUTHOR -> R.drawable.ic_author_24dp UNGROUPED -> R.drawable.ic_ungroup_24dp else -> R.drawable.ic_label_outline_24dp } 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 d0c46e8781..a176a17a02 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 @@ -20,6 +20,7 @@ import eu.kanade.tachiyomi.source.SourceManager import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.online.HttpSource import eu.kanade.tachiyomi.ui.base.presenter.BaseCoroutinePresenter +import eu.kanade.tachiyomi.ui.library.LibraryGroup.BY_AUTHOR import eu.kanade.tachiyomi.ui.library.LibraryGroup.BY_DEFAULT import eu.kanade.tachiyomi.ui.library.LibraryGroup.BY_SOURCE import eu.kanade.tachiyomi.ui.library.LibraryGroup.BY_TAG @@ -642,26 +643,33 @@ class LibraryPresenter( val tagItems: MutableMap = mutableMapOf() // internal function to make headers - fun makeOrGetHeader(name: String): LibraryHeaderItem { + fun makeOrGetHeader(name: String, checkNameSwap: Boolean = false): LibraryHeaderItem { return if (tagItems.containsKey(name)) { tagItems[name]!! } else { + if (checkNameSwap && name.contains(" ")) { + val swappedName = name.split(" ").reversed().joinToString(" ") + if (tagItems.containsKey(swappedName)) { + return tagItems[swappedName]!! + } + } val headerItem = LibraryHeaderItem({ getCategory(it) }, tagItems.count()) tagItems[name] = headerItem headerItem } } + val unknown = context.getString(R.string.unknown) val items = libraryManga.map { manga -> when (groupType) { BY_TAG -> { val tags = if (manga.genre.isNullOrBlank()) { - listOf("Unknown") + listOf(unknown) } else { manga.genre?.split(",")?.mapNotNull { val tag = it.trim().capitalizeWords() - if (tag.isBlank()) null else tag - } ?: listOf("Unknown") + tag.ifBlank { null } + } ?: listOf(unknown) } tags.map { LibraryItem(manga, makeOrGetHeader(it)) @@ -693,6 +701,23 @@ class LibraryPresenter( ), ) } + BY_AUTHOR -> { + if (manga.artist.isNullOrBlank() && manga.author.isNullOrBlank()) { + listOf(LibraryItem(manga, makeOrGetHeader(unknown))) + } else { + listOfNotNull( + manga.author.takeUnless { it.isNullOrBlank() }, + manga.artist.takeUnless { it.isNullOrBlank() }, + ).map { + it.split(",", "/", " x ", " - ", ignoreCase = true).mapNotNull { name -> + val author = name.trim() + author.ifBlank { null } + } + }.flatten().distinct().map { + LibraryItem(manga, makeOrGetHeader(it, true)) + } + } + } else -> listOf(LibraryItem(manga, makeOrGetHeader(mapStatus(manga.status)))) } }.flatten().toMutableList() @@ -712,13 +737,15 @@ class LibraryPresenter( } isHidden = getDynamicCategoryName(this) in hiddenDynamics } - }.sortedBy { - if (groupType == BY_TRACK_STATUS) { - mapTrackingOrder(it.name) - } else { - it.name - } - } + }.sortedWith( + compareBy(String.CASE_INSENSITIVE_ORDER) { + if (groupType == BY_TRACK_STATUS) { + mapTrackingOrder(it.name) + } else { + it.name + } + }, + ) if (preferences.collapsedDynamicAtBottom().get()) { headers = headers.filterNot { it.isHidden } + headers.filter { it.isHidden } } diff --git a/app/src/main/res/drawable/ic_author_24dp.xml b/app/src/main/res/drawable/ic_author_24dp.xml new file mode 100644 index 0000000000..98730cd907 --- /dev/null +++ b/app/src/main/res/drawable/ic_author_24dp.xml @@ -0,0 +1,5 @@ + + +