From a796bcc3fe2f6223dfe3bd84a9cfed313e57fe36 Mon Sep 17 00:00:00 2001 From: Jays2Kings Date: Sun, 28 Aug 2022 21:53:55 -0400 Subject: [PATCH] Add option to group by langauge Closes #1376 --- .../data/database/models/Category.kt | 2 + .../data/database/models/CategoryImpl.kt | 2 + .../tachiyomi/ui/library/LibraryController.kt | 2 + .../tachiyomi/ui/library/LibraryGroup.kt | 3 + .../ui/library/LibraryHeaderHolder.kt | 23 +++++++- .../tachiyomi/ui/library/LibraryPresenter.kt | 55 ++++++++++++++----- .../main/res/drawable/ic_translate_24dp.xml | 5 ++ .../res/layout/stats_details_controller.xml | 2 +- 8 files changed, 79 insertions(+), 15 deletions(-) create mode 100644 app/src/main/res/drawable/ic_translate_24dp.xml 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 027200a55d..125b230a9c 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 @@ -28,6 +28,8 @@ interface Category : Serializable { var sourceId: Long? + var langId: String? + fun isAscending(): Boolean { return ((mangaSort?.minus('a') ?: 0) % 2) != 1 } 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 2e08573745..64328bf018 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 @@ -22,6 +22,8 @@ class CategoryImpl : Category { override var sourceId: Long? = null + override var langId: String? = null + 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/ui/library/LibraryController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryController.kt index 885526bba8..f168dbe607 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 @@ -75,6 +75,7 @@ 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_LANGUAGE import eu.kanade.tachiyomi.ui.library.LibraryGroup.BY_SOURCE import eu.kanade.tachiyomi.ui.library.LibraryGroup.BY_STATUS import eu.kanade.tachiyomi.ui.library.LibraryGroup.BY_TAG @@ -506,6 +507,7 @@ class LibraryController( if (presenter.isLoggedIntoTracking) { groupItems.add(BY_TRACK_STATUS) } + groupItems.add(BY_LANGUAGE) if (presenter.allCategories.size > 1) { groupItems.add(UNGROUPED) } 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 143b0b2704..780d1ca913 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 @@ -10,6 +10,7 @@ object LibraryGroup { const val BY_STATUS = 3 const val BY_TRACK_STATUS = 4 const val BY_AUTHOR = 6 + const val BY_LANGUAGE = 7 const val UNGROUPED = 5 fun groupTypeStringRes(type: Int, hasCategories: Boolean = true): Int { @@ -19,6 +20,7 @@ object LibraryGroup { BY_SOURCE -> R.string.sources BY_TRACK_STATUS -> R.string.tracking_status BY_AUTHOR -> R.string.author + BY_LANGUAGE -> R.string.language UNGROUPED -> R.string.ungrouped else -> if (hasCategories) R.string.categories else R.string.ungrouped } @@ -31,6 +33,7 @@ object LibraryGroup { BY_TRACK_STATUS -> R.drawable.ic_sync_24dp BY_SOURCE -> R.drawable.ic_browse_24dp BY_AUTHOR -> R.drawable.ic_author_24dp + BY_LANGUAGE -> R.drawable.ic_translate_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/LibraryHeaderHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryHeaderHolder.kt index 733151acdb..236657143b 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 @@ -169,6 +169,9 @@ class LibraryHeaderHolder(val view: View, val adapter: LibraryCategoryAdapter) : val icon = adapter.sourceManager.get(category.sourceId!!)?.icon() icon?.setBounds(0, 0, 32.dpToPx, 32.dpToPx) binding.categoryTitle.setCompoundDrawablesRelative(icon, null, null, null) + } else if (category.langId != null) { + val icon = getFlagIcon(category.langId!!) ?: 0 + binding.categoryTitle.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, icon, 0) } else { binding.categoryTitle.setCompoundDrawablesRelative(null, null, null, null) } @@ -190,7 +193,7 @@ class LibraryHeaderHolder(val view: View, val adapter: LibraryCategoryAdapter) : binding.updateButton.isVisible = false setSelection() } - category.id ?: -1 < 0 -> { + (category.id ?: -1) < 0 -> { binding.collapseArrow.isVisible = false binding.checkbox.isVisible = false setRefreshing(false) @@ -211,6 +214,24 @@ class LibraryHeaderHolder(val view: View, val adapter: LibraryCategoryAdapter) : } } + @SuppressLint("DiscouragedApi") + fun getFlagIcon(lang: String): Int? { + val flagId = itemView.resources.getIdentifier( + "ic_flag_${lang.replace("-", "_")}", + "drawable", + itemView.context.packageName, + ).takeIf { it != 0 } ?: ( + if (lang.contains("-")) { + itemView.resources.getIdentifier( + "ic_flag_${lang.split("-").first()}", + "drawable", + itemView.context.packageName, + ).takeIf { it != 0 } + } else null + ) + return flagId + } + fun setRefreshing(refreshing: Boolean) { binding.updateButton.isClickable = !refreshing if (refreshing) { 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 d19f99e98b..c4d22b9e4c 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 @@ -22,6 +22,7 @@ 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_LANGUAGE import eu.kanade.tachiyomi.ui.library.LibraryGroup.BY_SOURCE import eu.kanade.tachiyomi.ui.library.LibraryGroup.BY_TAG import eu.kanade.tachiyomi.ui.library.LibraryGroup.BY_TRACK_STATUS @@ -415,15 +416,15 @@ class LibraryPresenter( private fun setSourceLanguage(itemList: List) { val showLanguageBadges = preferences.languageBadge().get() for (item in itemList) { - item.sourceLanguage = if (showLanguageBadges) { - if (item.manga.isLocal()) { - LocalSource.getMangaLang(item.manga, context) - } else { - sourceManager.get(item.manga.source)?.lang - } - } else { - null - } + item.sourceLanguage = if (showLanguageBadges) getLanguage(item.manga) else null + } + } + + private fun getLanguage(manga: Manga): String? { + return if (manga.isLocal()) { + LocalSource.getMangaLang(manga, context) + } else { + sourceManager.get(manga.source)?.lang } } @@ -730,7 +731,25 @@ class LibraryPresenter( } } } - else -> listOf(LibraryItem(manga, makeOrGetHeader(context.mapStatus(manga.status)), viewContext)) + BY_LANGUAGE -> { + val lang = getLanguage(manga) + listOf( + LibraryItem( + manga, + makeOrGetHeader( + lang?.plus(langSplitter)?.plus( + run { + val locale = Locale.forLanguageTag(lang) + locale.getDisplayName(locale) + .replaceFirstChar { it.uppercase(locale) } + }, + ) ?: unknown, + ), + viewContext, + ), + ) + } + else /* BY_STATUS */ -> listOf(LibraryItem(manga, makeOrGetHeader(context.mapStatus(manga.status)), viewContext)) } }.flatten().toMutableList() @@ -746,6 +765,10 @@ class LibraryPresenter( val split = name.split(sourceSplitter) name = split.first() sourceId = split.last().toLongOrNull() + } else if (name.contains(langSplitter)) { + val split = name.split(langSplitter) + name = split.last() + langId = split.first() } isHidden = getDynamicCategoryName(this) in hiddenDynamics } @@ -764,7 +787,13 @@ class LibraryPresenter( headers.forEach { category -> val catId = category.id ?: return@forEach val headerItem = - tagItems[if (category.sourceId != null) "${category.name}$sourceSplitter${category.sourceId}" else category.name] + tagItems[ + when { + category.sourceId != null -> "${category.name}$sourceSplitter${category.sourceId}" + category.langId != null -> "${category.langId}$langSplitter${category.name}" + else -> category.name + }, + ] if (category.isHidden) { val mangaToRemove = items.filter { it.header.catId == catId } val mergedTitle = mangaToRemove.joinToString("-") { @@ -1052,8 +1081,7 @@ class LibraryPresenter( private fun getDynamicCategoryName(category: Category): String = groupType.toString() + dynamicCategorySplitter + ( - category.sourceId?.toString() - ?: category.name + category.sourceId?.toString() ?: category.langId ?: category.name ) fun toggleAllCategoryVisibility() { @@ -1162,6 +1190,7 @@ class LibraryPresenter( private var lastLibraryItems: List? = null private var lastCategories: List? = null private const val sourceSplitter = "◘•◘" + private const val langSplitter = "⨼⨦⨠" private const val dynamicCategorySplitter = "▄╪\t▄╪\t▄" private val randomTags = arrayOf(0, 1, 2) diff --git a/app/src/main/res/drawable/ic_translate_24dp.xml b/app/src/main/res/drawable/ic_translate_24dp.xml new file mode 100644 index 0000000000..1a73c2d644 --- /dev/null +++ b/app/src/main/res/drawable/ic_translate_24dp.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/layout/stats_details_controller.xml b/app/src/main/res/layout/stats_details_controller.xml index da2025e015..07ef7e58fb 100644 --- a/app/src/main/res/layout/stats_details_controller.xml +++ b/app/src/main/res/layout/stats_details_controller.xml @@ -145,7 +145,7 @@ android:text="@string/language" android:textColor="?attr/colorOnBackground" app:checkedIconEnabled="false" - app:chipIcon="@drawable/ic_language_24dp" + app:chipIcon="@drawable/ic_translate_24dp" app:chipIconEnabled="false" app:chipIconTint="?attr/colorOnBackground" app:chipStrokeColor="?attr/colorSecondary"