diff --git a/app/src/main/java/eu/kanade/presentation/library/components/LibraryBadges.kt b/app/src/main/java/eu/kanade/presentation/library/components/LibraryBadges.kt index 6e317852a..8197c3c16 100644 --- a/app/src/main/java/eu/kanade/presentation/library/components/LibraryBadges.kt +++ b/app/src/main/java/eu/kanade/presentation/library/components/LibraryBadges.kt @@ -91,6 +91,7 @@ fun SourceIconBadge( Badge( imageVector = Icons.Filled.Warning, iconColor = MaterialTheme.colorScheme.error, + color = MaterialTheme.colorScheme.errorContainer, ) } icon != null -> { diff --git a/flagkit/src/main/java/com/murgupluoglu/flagkit/FlagKit.kt b/flagkit/src/main/java/com/murgupluoglu/flagkit/FlagKit.kt index fe0d2d51f..ada4a379b 100644 --- a/flagkit/src/main/java/com/murgupluoglu/flagkit/FlagKit.kt +++ b/flagkit/src/main/java/com/murgupluoglu/flagkit/FlagKit.kt @@ -37,7 +37,6 @@ object FlagKit { return resourceId } - @Suppress("unused") fun getAllAvailableCodes(): List { return listOf( "ad", diff --git a/presentation-core/src/main/java/tachiyomi/presentation/core/icons/FlagEmoji.kt b/presentation-core/src/main/java/tachiyomi/presentation/core/icons/FlagEmoji.kt new file mode 100644 index 000000000..fbe664bc1 --- /dev/null +++ b/presentation-core/src/main/java/tachiyomi/presentation/core/icons/FlagEmoji.kt @@ -0,0 +1,557 @@ +package tachiyomi.presentation.core.icons + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.FlowRow +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.size +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import tachiyomi.presentation.core.icons.FlagEmoji.Companion.getEmojiCountryFlag +import tachiyomi.presentation.core.icons.FlagEmoji.Companion.getEmojiLangFlag + +class FlagEmoji { + companion object { + /** + * The regional indicators go from 0x1F1E6 (A) to 0x1F1FF (Z). + * This is the A regional indicator value minus 65 decimal so + * that we can just add this to the A-Z char + */ + private const val REGIONAL_INDICATOR_OFFSET: Int = 0x1F1A5 + + private fun getRegionalIndicatorSymbol(character: Char): String { + require(!(character < 'A' || character > 'Z')) { "Invalid character: you must use A-Z" } + return String(Character.toChars(REGIONAL_INDICATOR_OFFSET + character.code)) + } + + fun getEmojiCountryFlag(countryCode: String): String { + val code = countryCode.uppercase() + return getRegionalIndicatorSymbol(code[0]) + getRegionalIndicatorSymbol(code[1]) + } + + fun getEmojiLangFlag(lang: String): String { + return lang2Country(lang)?.let { getEmojiCountryFlag(it) } ?: "\uD83C\uDF0E" + } + + private fun lang2Country(lang: String): String? { + return when (lang) { + // "all" -> R.drawable.ic_flag_all + // "other" -> R.drawable.globe + "af" -> "za" // Afrikaans -> South Africa, ZA + "am" -> "et" // Amharic -> Ethiopia, ET + "ar" -> "eg" // Arabic -> Egypt, EG - Saudi Arabia, SA + "az" -> "az" // Azerbaijani -> Azerbaijan, AZ + "be" -> "by" // Belarusian -> Belarus, BY + "bg" -> "bg" // Bulgarian -> Bulgaria, BG + "bn" -> "bd" // Bengali -> Bangladesh, BD + "br" -> "fr" // Breton -> France, FR + "bs" -> "ba" // Bosnia and Herzegovina, BA + "ca" -> "es" // Catalan -> Spain, ES + "ceb" -> "ph" // Cebuano -> Philippines, PH + "cn" -> "cn" // Chinese -> China, CN + "co" -> "es" // Corsican -> Spain, ES + "cs" -> "cz" // Czech -> Czech Republic, CZ + "da" -> "dk" // Danish -> Denmark, DK + "de" -> "de" // German -> Germany, DE + "el" -> "gr" // Greek -> Greece, GR + "en" -> "us" // English -> United States, US + // "eo" -> "ic_flag_esperanto" // Esperanto -> no country + "es-419" -> "mx" // Spanish -> Mexico MX, Latin America, Latin America + "es" -> "es" // Spanish -> Spain, ES + "et" -> "ee" // Estonian -> Estonia, EE + "eu" -> "es" // Basque -> Spain, ES + "fa" -> "ir" // Persian -> Iran, IR + "fi" -> "fi" // Finnish -> Finland, FI + "fil" -> "ph" // Filipino -> Philippines, PH + "fo" -> "fo" // Faroese -> Faroe Island, FO + "fr" -> "fr" // French -> France, FR + "ga" -> "ie" // Irish -> Ireland, IE + "gn" -> "py" // Guarani -> Paraguay, PY + "gu" -> "in_" // Gujarati -> India, IN + "ha" -> "ng" // Hausa -> Nigeria, NG + "he" -> "il" // Hebrew -> Israel, IL + "hi" -> "in_" // Hindi -> India, IN + "hr" -> "hr" // Croatian -> Croatia, HR + "ht" -> "ht" // Haitian -> Haiti, HT + "hu" -> "hu" // Hungarian -> Hungary, HU + "hy" -> "am" // Armenian -> Armenia, AM + "id" -> "id" // Indonesian -> Indonesia, ID + "ig" -> "ng" // Igbo -> Nigeria, NG + "is" -> "is_" // Icelandic -> Iceland, IS + "it" -> "it" // Italian -> Italy, IT + "ja" -> "jp" // Japanese -> Japan, JP + "jv" -> "id" // Javanese -> Indonesia, ID + "ka" -> "ge" // Georgian -> Georgia, GE + "kk" -> "kz" // Kazakh -> Kazakhstan, KZ + "km" -> "kh" // Khmer -> Cambodia, KH + "kn" -> "in_" // Kannada -> India, IN + "ko" -> "kr" // Korean -> South Korea, KR + "kr" -> "ng" // Kanuri -> Nigeria, NG + "ku" -> "iq" // Kurdish -> Iraq, IQ + "ky" -> "kg" // Kyrgyz -> Kyrgyzstan, KG + // "la" -> "ic_flag_la" // Latin -> Latin America, Latin America + "lb" -> "lu" // Luxembourgish -> Luxembourg, LU + "lmo" -> "it" // Lombard, Italy, IT + "lo" -> "la" // Lao -> Laos, LA + "lt" -> "lt" // Lithuanian -> Lithuania, LT + "lv" -> "lv" // Latvian -> Latvia, LV + "mg" -> "mg" // Malagasy -> Madagascar, MG + "mi" -> "nz" // Maori -> New Zealand, NZ + "mk" -> "mk" // Macedonian -> Macedonia, MK + "ml" -> "in_" // Malayalam -> India, IN + "mn" -> "mn" // Mongolian -> Mongolia, MN + "mo" -> "md" // Moldavian -> Moldova, MD + "mr" -> "in_" // Marathi -> India, IN + "ms" -> "my" // Malay -> Malaysia, MY + "mt" -> "mt" // Maltese -> Malta, MT + "my" -> "mm" // Myanmar -> Myanmar, MM + "ne" -> "np" // Nepali -> Nepal, NP + "nl" -> "nl" // Dutch -> Netherlands, NL + "no" -> "no" // Norwegian -> Norway, NO + "ny" -> "mw" // Nyanja -> Malawi, MW + "pl" -> "pl" // Polish -> Poland, PL + "ps" -> "af" // Pashto -> Afghanistan, AF - Pakistan, PK + "pt-BR" -> "br" // Portuguese, Brazil, BR + "pt-PT" -> "pt" // Portuguese, Portugal, PT + "pt" -> "pt" // Portuguese -> Portugal, PT + "rm" -> "ch" // Romansh -> Switzerland, SW + "ro" -> "ro" // Romanian -> Romania, RO + "ru" -> "ru" // Russian -> Russia, RU + "sd" -> "pk" // Sindhi -> Pakistan, PK + "sh" -> "hr" // Serbo-Croatian -> Serbia, HR + "si" -> "lk" // Sinhalese -> Sri Lanka, LK + "sk" -> "sk" // Slovak -> Slovakia, SK + "sl" -> "si" // Slovenian -> Slovenia, SI + "sm" -> "ws" // Samoan -> Samoa, WS + "sn" -> "zw" // Shona -> Zimbabwe, ZW + "so" -> "so" // Somali -> Somalia, SO + "sq" -> "al" // Albanian -> Albania, AL + "sr" -> "hr" // Serbian -> Serbia, HR + "st" -> "ls" // Sesotho -> South Africa, ZA - Lesotho, LS + "sv" -> "se" // Swedish -> Sweden, SE + "sw" -> "tz" // Swahili -> Tanzania, TZ - Kenya, KE + "ta" -> "in_" // Tamil -> India, IN + "te" -> "in_" // Telugu -> India, IN + "tg" -> "tj" // Tajik -> Tajikistan, TJ + "th" -> "th" // Thai -> Thailand, TH + "ti" -> "er" // Tigrinya -> Eritrea, ER + "tk" -> "tm" // Turkmen -> Turkmenistan, TM + "tl" -> "ph" // Filipino -> Philippines, PH + "to" -> "to" // Tonga -> Tonga, TO + "tr" -> "tr" // Turkish -> Turkey, TR + "uk" -> "ua" // Ukrainian -> Ukraine, UA + "ur" -> "pk" // Urdu -> Pakistan, PK + "uz" -> "uz" // Uzbek -> Uzbekistan, UZ + "vec" -> "it" // Venetian -> Italy, IT + "vi" -> "vn" // Vietnamese -> Vietnam, VN + "yo" -> "ng" // Yoruba -> Nigeria, NG + "zh-Hans" -> "cn" // Chinese, simplified -> China, CN + "zh-Hant" -> "tw" // Chinese, traditional -> Taiwan, TW + "zh" -> "cn" // Chinese -> China, CN + "zu" -> "za" // Zulu -> South Africa, ZA + else -> null + } + } + } +} + +@Preview +@Composable +private fun Preview() { + val langList = listOf( + "af", + "am", + "ar", + "az", + "be", + "bg", + "bn", + "br", + "bs", + "ca", + "ceb", + "cn", + "co", + "cs", + "da", + "de", + "el", + "en", + // "eo", + "es-419", + "es", + "et", + "eu", + "fa", + "fi", + "fil", + "fo", + "fr", + "ga", + "gn", + "gu", + "ha", + "he", + "hi", + "hr", + "ht", + "hu", + "hy", + "id", + "ig", + "is", + "it", + "ja", + "jv", + "ka", + "kk", + "km", + "kn", + "ko", + "kr", + "ku", + "ky", + // "la", + "lb", + "lmo", + "lo", + "lt", + "lv", + "mg", + "mi", + "mk", + "ml", + "mn", + "mo", + "mr", + "ms", + "mt", + "my", + "ne", + "nl", + "no", + "ny", + "pl", + "ps", + "pt-BR", + "pt-PT", + "pt", + "rm", + "ro", + "ru", + "sd", + "sh", + "si", + "sk", + "sl", + "sm", + "sn", + "so", + "sq", + "sr", + "st", + "sv", + "sw", + "ta", + "te", + "tg", + "th", + "ti", + "tk", + "tl", + "to", + "tr", + "uk", + "ur", + "uz", + "vec", + "vi", + "yo", + "zh-Hans", + "zh-Hant", + "zh", + "zu", + ) + + val countryList = listOf( + "ad", + "ae", + "af", + "ag", + "ai", + "al", + "am", + "ao", + "ar", + "as", + "at", + "au", + "aw", + "ax", + "az", + "ba", + "bb", + "bd", + "be", + "bf", + "bg", + "bh", + "bi", + "bj", + "bl", + "bm", + "bn", + "bo", + "br", + "bs", + "bt", + "bv", + "bw", + "by", + "bz", + "ca", + "cc", + "cd", + "cf", + "cg", + "ch", + "ci", + "ck", + "cl", + "cm", + "cn", + "co", + "cr", + "cu", + "cv", + "cw", + "cx", + "cy", + "cz", + "de", + "dj", + "dk", + "dm", + "do", + "dz", + "ec", + "ee", + "eg", + "er", + "es", + "et", + "eu", + "fi", + "fj", + "fk", + "fm", + "fo", + "fr", + "ga", + "gb", + "gb_eng", + "gb_nir", + "gb_sct", + "gb_wls", + "gb_zet", + "gd", + "ge", + "gf", + "gg", + "gh", + "gi", + "gl", + "gm", + "gn", + "gp", + "gq", + "gr", + "gs", + "gt", + "gu", + "gw", + "gy", + "hk", + "hm", + "hn", + "hr", + "ht", + "hu", + "id", + "ie", + "il", + "im", + "in", + "io", + "iq", + "ir", + "is", + "it", + "je", + "jm", + "jo", + "jp", + "ke", + "kg", + "kh", + "ki", + "km", + "kn", + "kp", + "kr", + "kw", + "ky", + "kz", + "la", + "lb", + "lc", + "li", + "lk", + "lr", + "ls", + "lt", + "lu", + "lv", + "ly", + "ma", + "mc", + "md", + "me", + "mf", + "mg", + "mh", + "mk", + "ml", + "mm", + "mn", + "mo", + "mp", + "mq", + "mr", + "ms", + "mt", + "mu", + "mv", + "mw", + "mx", + "my", + "mz", + "na", + "nc", + "ne", + "nf", + "ng", + "ni", + "nl", + "no", + "np", + "nr", + "nu", + "nz", + "om", + "pa", + "pe", + "pf", + "pg", + "ph", + "pk", + "pl", + "pm", + "pn", + "pr", + "ps", + "pt", + "pw", + "py", + "qa", + "re", + "ro", + "rs", + "ru", + "rw", + "sa", + "sb", + "sc", + "sd", + "se", + "sg", + "sh", + "si", + "sj", + "sk", + "sl", + "sm", + "sn", + "so", + "sr", + "ss", + "st", + "sv", + "sx", + "sy", + "sz", + "tc", + "td", + "tf", + "tg", + "th", + "tj", + "tk", + "tl", + "tm", + "tn", + "to", + "tr", + "tt", + "tv", + "tw", + "tz", + "ua", + "ug", + "um", + "us", + "us_ca", + "uy", + "uz", + "va", + "vc", + "ve", + "vg", + "vi", + "vn", + "vu", + "wf", + "ws", + "xk", + "ye", + "yt", + "za", + "zm", + "zw", + ) + Column { + FlowRow { + Text(text = "\uD83C\uDF0E") + Text(text = "\uD83C\uDF0D") + Text(text = getEmojiCountryFlag("vn")) + Text(text = getEmojiCountryFlag("us")) + Text(text = getEmojiCountryFlag("eu")) + Text(text = getEmojiLangFlag("en")) + Text(text = getEmojiLangFlag("all")) + } + Spacer(modifier = Modifier.size(5.dp)) + FlowRow { + langList.forEach { + Text(text = getEmojiLangFlag(it)) + } + } + Spacer(modifier = Modifier.size(5.dp)) + FlowRow { + countryList.forEach { + Text(text = getEmojiCountryFlag(it)) + } + } + } +} diff --git a/source-api/build.gradle.kts b/source-api/build.gradle.kts index b9a953a95..7fda6892a 100644 --- a/source-api/build.gradle.kts +++ b/source-api/build.gradle.kts @@ -46,6 +46,10 @@ android { } } +dependencies { + implementation(project(":presentation-core")) +} + tasks { withType { compilerOptions.freeCompilerArgs.addAll( diff --git a/source-api/src/commonMain/kotlin/eu/kanade/tachiyomi/source/online/HttpSource.kt b/source-api/src/commonMain/kotlin/eu/kanade/tachiyomi/source/online/HttpSource.kt index cfeec96b6..316227d43 100644 --- a/source-api/src/commonMain/kotlin/eu/kanade/tachiyomi/source/online/HttpSource.kt +++ b/source-api/src/commonMain/kotlin/eu/kanade/tachiyomi/source/online/HttpSource.kt @@ -24,6 +24,7 @@ import okhttp3.Request import okhttp3.Response import rx.Observable import tachiyomi.core.common.util.lang.awaitSingle +import tachiyomi.presentation.core.icons.FlagEmoji import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get import java.net.URI @@ -139,7 +140,9 @@ abstract class HttpSource : CatalogueSource { /** * Visible name of the source. */ - override fun toString() = "$name (${lang.uppercase()})" + override fun toString() = "$name (${ + FlagEmoji.getEmojiLangFlag(lang) + })" /** * Get a page with a list of manga.