mirror of
https://gitlab.futo.org/keyboard/latinime.git
synced 2024-09-28 14:54:30 +01:00
Move layout-language mapping to mapping.yaml, update AddLanguage screen
This commit is contained in:
parent
c1d0787395
commit
6bcc162f1e
@ -1,5 +1,5 @@
|
||||
name: Serbian QWERTZ
|
||||
languages: sr-ZZ
|
||||
languages: sr-Latn
|
||||
rows:
|
||||
- letters: q w e r t z u i o p š
|
||||
- letters: a s d f g h j k l č ć
|
||||
|
@ -1,4 +1,4 @@
|
||||
name: Русский
|
||||
name: East Slavic
|
||||
languages: ru be bg bn kk ky uk
|
||||
rows:
|
||||
- letters: й ц у к е н г ш щ з х
|
||||
|
521
java/assets/layouts/mapping.yaml
Normal file
521
java/assets/layouts/mapping.yaml
Normal file
@ -0,0 +1,521 @@
|
||||
languages:
|
||||
af:
|
||||
- qwerty
|
||||
- qwertz
|
||||
- dvorak
|
||||
- azerty
|
||||
- colemak
|
||||
- bepo
|
||||
- pcqwerty
|
||||
- nordic
|
||||
ar:
|
||||
- arabic
|
||||
- lulua
|
||||
az_AZ:
|
||||
- qwerty
|
||||
- qwertz
|
||||
- dvorak
|
||||
- azerty
|
||||
- colemak
|
||||
- bepo
|
||||
- pcqwerty
|
||||
- nordic
|
||||
be_BY:
|
||||
- east_slavic
|
||||
- russian_student
|
||||
- russian_yavert
|
||||
- russian_yazhert
|
||||
bg:
|
||||
- bulgarian
|
||||
- bulgarian_bds
|
||||
bn_BD:
|
||||
- bengali_akkhor
|
||||
bn_IN:
|
||||
- bengali
|
||||
ca:
|
||||
- spanish
|
||||
- qwerty
|
||||
- qwertz
|
||||
- dvorak
|
||||
- azerty
|
||||
- colemak
|
||||
- bepo
|
||||
- pcqwerty
|
||||
- nordic
|
||||
ckb:
|
||||
- kurdish
|
||||
cs:
|
||||
- qwertz
|
||||
- qwerty
|
||||
- dvorak
|
||||
- azerty
|
||||
- colemak
|
||||
- bepo
|
||||
- pcqwerty
|
||||
- nordic
|
||||
da:
|
||||
- nordic
|
||||
- qwerty
|
||||
- qwertz
|
||||
- dvorak
|
||||
- azerty
|
||||
- colemak
|
||||
- bepo
|
||||
- pcqwerty
|
||||
de:
|
||||
- german
|
||||
- qwertz
|
||||
- swiss
|
||||
- qwerty
|
||||
- dvorak
|
||||
- azerty
|
||||
- colemak
|
||||
- bepo
|
||||
- pcqwerty
|
||||
- nordic
|
||||
de_CH:
|
||||
- swiss
|
||||
- qwerty
|
||||
- qwertz
|
||||
- dvorak
|
||||
- azerty
|
||||
- colemak
|
||||
- bepo
|
||||
- pcqwerty
|
||||
- nordic
|
||||
el:
|
||||
- greek
|
||||
- qwerty
|
||||
- qwertz
|
||||
- dvorak
|
||||
- azerty
|
||||
- colemak
|
||||
- bepo
|
||||
- pcqwerty
|
||||
- nordic
|
||||
en_GB:
|
||||
- qwerty
|
||||
- qwertz
|
||||
- dvorak
|
||||
- azerty
|
||||
- colemak
|
||||
- bepo
|
||||
- pcqwerty
|
||||
- nordic
|
||||
en_IN:
|
||||
- qwerty
|
||||
- qwertz
|
||||
- dvorak
|
||||
- azerty
|
||||
- colemak
|
||||
- bepo
|
||||
- pcqwerty
|
||||
- nordic
|
||||
en_US:
|
||||
- qwerty
|
||||
- qwertz
|
||||
- dvorak
|
||||
- azerty
|
||||
- colemak
|
||||
- bepo
|
||||
- pcqwerty
|
||||
- nordic
|
||||
eo:
|
||||
- spanish
|
||||
- qwerty
|
||||
- qwertz
|
||||
- dvorak
|
||||
- azerty
|
||||
- colemak
|
||||
- bepo
|
||||
- pcqwerty
|
||||
- nordic
|
||||
es:
|
||||
- spanish
|
||||
- qwerty
|
||||
- qwertz
|
||||
- dvorak
|
||||
- azerty
|
||||
- colemak
|
||||
- bepo
|
||||
- pcqwerty
|
||||
- nordic
|
||||
es_419:
|
||||
- spanish
|
||||
- qwerty
|
||||
- qwertz
|
||||
- dvorak
|
||||
- azerty
|
||||
- colemak
|
||||
- bepo
|
||||
- pcqwerty
|
||||
- nordic
|
||||
es_US:
|
||||
- spanish
|
||||
- qwerty
|
||||
- qwertz
|
||||
- dvorak
|
||||
- azerty
|
||||
- colemak
|
||||
- bepo
|
||||
- pcqwerty
|
||||
- nordic
|
||||
et_EE:
|
||||
- nordic
|
||||
- qwerty
|
||||
- qwertz
|
||||
- dvorak
|
||||
- azerty
|
||||
- colemak
|
||||
- bepo
|
||||
- pcqwerty
|
||||
eu_ES:
|
||||
- spanish
|
||||
- qwerty
|
||||
- qwertz
|
||||
- dvorak
|
||||
- azerty
|
||||
- colemak
|
||||
- bepo
|
||||
- pcqwerty
|
||||
- nordic
|
||||
fa:
|
||||
- farsi
|
||||
fi:
|
||||
- nordic
|
||||
- qwerty
|
||||
- qwertz
|
||||
- dvorak
|
||||
- azerty
|
||||
- colemak
|
||||
- bepo
|
||||
- pcqwerty
|
||||
fr:
|
||||
- azerty
|
||||
- swiss
|
||||
- qwerty
|
||||
- qwertz
|
||||
- dvorak
|
||||
- colemak
|
||||
- bepo
|
||||
- pcqwerty
|
||||
- nordic
|
||||
fr_CA:
|
||||
- qwerty
|
||||
- swiss
|
||||
- qwertz
|
||||
- dvorak
|
||||
- azerty
|
||||
- colemak
|
||||
- bepo
|
||||
- pcqwerty
|
||||
- nordic
|
||||
fr_CH:
|
||||
- swiss
|
||||
- qwerty
|
||||
- qwertz
|
||||
- dvorak
|
||||
- azerty
|
||||
- colemak
|
||||
- bepo
|
||||
- pcqwerty
|
||||
- nordic
|
||||
gl_ES:
|
||||
- spanish
|
||||
- qwerty
|
||||
- qwertz
|
||||
- dvorak
|
||||
- azerty
|
||||
- colemak
|
||||
- bepo
|
||||
- pcqwerty
|
||||
- nordic
|
||||
hi:
|
||||
- hindi
|
||||
- hindi_compact
|
||||
hi_Latn:
|
||||
- qwerty
|
||||
- qwertz
|
||||
- dvorak
|
||||
- azerty
|
||||
- colemak
|
||||
- bepo
|
||||
- pcqwerty
|
||||
- nordic
|
||||
hr:
|
||||
- qwertz
|
||||
- qwerty
|
||||
- dvorak
|
||||
- azerty
|
||||
- colemak
|
||||
- bepo
|
||||
- pcqwerty
|
||||
- nordic
|
||||
hu:
|
||||
- qwertz
|
||||
- qwerty
|
||||
- dvorak
|
||||
- azerty
|
||||
- colemak
|
||||
- bepo
|
||||
- pcqwerty
|
||||
- nordic
|
||||
hy_AM:
|
||||
- armenian_phonetic
|
||||
in:
|
||||
- qwerty
|
||||
- qwertz
|
||||
- dvorak
|
||||
- azerty
|
||||
- colemak
|
||||
- bepo
|
||||
- pcqwerty
|
||||
- nordic
|
||||
is:
|
||||
- qwerty
|
||||
- qwertz
|
||||
- dvorak
|
||||
- azerty
|
||||
- colemak
|
||||
- bepo
|
||||
- pcqwerty
|
||||
- nordic
|
||||
it:
|
||||
- qwerty
|
||||
- qwertz
|
||||
- dvorak
|
||||
- azerty
|
||||
- colemak
|
||||
- bepo
|
||||
- pcqwerty
|
||||
- nordic
|
||||
it_CH:
|
||||
- swiss
|
||||
- qwerty
|
||||
- qwertz
|
||||
- dvorak
|
||||
- azerty
|
||||
- colemak
|
||||
- bepo
|
||||
- pcqwerty
|
||||
- nordic
|
||||
iw:
|
||||
- hebrew
|
||||
ka_GE:
|
||||
- georgian
|
||||
kk:
|
||||
- east_slavic
|
||||
- russian_student
|
||||
- russian_yavert
|
||||
- russian_yazhert
|
||||
km_KH:
|
||||
- khmer
|
||||
kn_IN:
|
||||
- kannada
|
||||
ky:
|
||||
- east_slavic
|
||||
- russian_student
|
||||
- russian_yavert
|
||||
- russian_yazhert
|
||||
lo_LA:
|
||||
- lao
|
||||
lt:
|
||||
- qwerty
|
||||
- qwertz
|
||||
- dvorak
|
||||
- azerty
|
||||
- colemak
|
||||
- bepo
|
||||
- pcqwerty
|
||||
- nordic
|
||||
lv:
|
||||
- qwerty
|
||||
- qwertz
|
||||
- dvorak
|
||||
- azerty
|
||||
- colemak
|
||||
- bepo
|
||||
- pcqwerty
|
||||
- nordic
|
||||
mk:
|
||||
- south_slavic
|
||||
ml_IN:
|
||||
- malayalam
|
||||
mn_MN:
|
||||
- mongolian
|
||||
mr_IN:
|
||||
- marathi
|
||||
ms_MY:
|
||||
- qwerty
|
||||
- qwertz
|
||||
- dvorak
|
||||
- azerty
|
||||
- colemak
|
||||
- bepo
|
||||
- pcqwerty
|
||||
- nordic
|
||||
nb:
|
||||
- nordic
|
||||
ne_NP:
|
||||
- nepali_romanized
|
||||
- nepali_traditional
|
||||
nl:
|
||||
- qwerty
|
||||
- qwertz
|
||||
- dvorak
|
||||
- azerty
|
||||
- colemak
|
||||
- bepo
|
||||
- pcqwerty
|
||||
- nordic
|
||||
nl_BE:
|
||||
- azerty
|
||||
- qwerty
|
||||
- qwertz
|
||||
- dvorak
|
||||
- colemak
|
||||
- bepo
|
||||
- pcqwerty
|
||||
- nordic
|
||||
pl:
|
||||
- qwerty
|
||||
- qwertz
|
||||
- dvorak
|
||||
- azerty
|
||||
- colemak
|
||||
- bepo
|
||||
- pcqwerty
|
||||
- nordic
|
||||
pt_BR:
|
||||
- qwerty
|
||||
- qwertz
|
||||
- dvorak
|
||||
- azerty
|
||||
- colemak
|
||||
- bepo
|
||||
- pcqwerty
|
||||
- nordic
|
||||
pt_PT:
|
||||
- qwerty
|
||||
- qwertz
|
||||
- dvorak
|
||||
- azerty
|
||||
- colemak
|
||||
- bepo
|
||||
- pcqwerty
|
||||
- nordic
|
||||
ro:
|
||||
- qwerty
|
||||
- qwertz
|
||||
- dvorak
|
||||
- azerty
|
||||
- colemak
|
||||
- bepo
|
||||
- pcqwerty
|
||||
- nordic
|
||||
ru:
|
||||
- east_slavic
|
||||
- russian_student
|
||||
- russian_yavert
|
||||
- russian_yazhert
|
||||
si_LK:
|
||||
- sinhala
|
||||
sk:
|
||||
- qwerty
|
||||
- qwertz
|
||||
- dvorak
|
||||
- azerty
|
||||
- colemak
|
||||
- bepo
|
||||
- pcqwerty
|
||||
- nordic
|
||||
sl:
|
||||
- qwerty
|
||||
- qwertz
|
||||
- dvorak
|
||||
- azerty
|
||||
- colemak
|
||||
- bepo
|
||||
- pcqwerty
|
||||
- nordic
|
||||
sr:
|
||||
- south_slavic
|
||||
sr_Latn:
|
||||
- serbian_qwertz
|
||||
sv:
|
||||
- nordic
|
||||
sw:
|
||||
- qwerty
|
||||
- qwertz
|
||||
- dvorak
|
||||
- azerty
|
||||
- colemak
|
||||
- bepo
|
||||
- pcqwerty
|
||||
- nordic
|
||||
ta_IN:
|
||||
- tamil
|
||||
ta_LK:
|
||||
- tamil
|
||||
ta_SG:
|
||||
- tamil
|
||||
te_IN:
|
||||
- telugu
|
||||
th:
|
||||
- thai
|
||||
tl:
|
||||
- spanish
|
||||
- qwerty
|
||||
- qwertz
|
||||
- dvorak
|
||||
- azerty
|
||||
- colemak
|
||||
- bepo
|
||||
- pcqwerty
|
||||
- nordic
|
||||
tr:
|
||||
- turkish
|
||||
- qwerty
|
||||
- qwertz
|
||||
- dvorak
|
||||
- azerty
|
||||
- colemak
|
||||
- bepo
|
||||
- pcqwerty
|
||||
- nordic
|
||||
uk:
|
||||
- east_slavic
|
||||
- russian_student
|
||||
- russian_yavert
|
||||
- russian_yazhert
|
||||
uz_UZ:
|
||||
- uzbek
|
||||
vi:
|
||||
- qwerty
|
||||
- qwertz
|
||||
- dvorak
|
||||
- azerty
|
||||
- colemak
|
||||
- bepo
|
||||
- pcqwerty
|
||||
- nordic
|
||||
zu:
|
||||
- qwerty
|
||||
- qwertz
|
||||
- dvorak
|
||||
- azerty
|
||||
- colemak
|
||||
- bepo
|
||||
- pcqwerty
|
||||
- nordic
|
||||
zz:
|
||||
- qwerty
|
||||
- qwertz
|
||||
- dvorak
|
||||
- azerty
|
||||
- colemak
|
||||
- bepo
|
||||
- pcqwerty
|
||||
- nordic
|
||||
ipa:
|
||||
- ipa
|
@ -43,10 +43,10 @@ import org.futo.inputmethod.latin.uix.setSettingBlocking
|
||||
import org.futo.inputmethod.latin.uix.settings.NavigationItem
|
||||
import org.futo.inputmethod.latin.uix.settings.NavigationItemStyle
|
||||
import org.futo.inputmethod.latin.uix.settings.SettingsActivity
|
||||
import org.futo.inputmethod.latin.uix.settings.pages.LocaleLayoutMap
|
||||
import org.futo.inputmethod.latin.uix.settings.useDataStoreValue
|
||||
import org.futo.inputmethod.latin.uix.theme.Typography
|
||||
import org.futo.inputmethod.latin.utils.SubtypeLocaleUtils
|
||||
import org.futo.inputmethod.v2keyboard.LayoutManager
|
||||
import java.util.Locale
|
||||
import kotlin.math.sign
|
||||
|
||||
@ -110,7 +110,7 @@ object Subtypes {
|
||||
var numAdded = 0
|
||||
for(i in 0 until locales.size()) {
|
||||
val locale = locales.get(i).stripExtensionsIfNeeded()
|
||||
val layout = findClosestLocaleLayouts(locale).firstOrNull() ?: continue
|
||||
val layout = findClosestLocaleLayouts(context, locale).firstOrNull() ?: continue
|
||||
|
||||
addLanguage(context, locale, layout)
|
||||
numAdded += 1
|
||||
@ -124,10 +124,8 @@ object Subtypes {
|
||||
context.setSettingBlocking(ActiveSubtype.key, context.getSettingBlocking(SubtypesSetting).firstOrNull() ?: return)
|
||||
}
|
||||
|
||||
fun findClosestLocaleLayouts(locale: Locale): List<String> {
|
||||
val supportedLocales = LocaleLayoutMap.toList().associate {
|
||||
getLocale(it.first) to it.second
|
||||
}
|
||||
fun findClosestLocaleLayouts(context: Context, locale: Locale): List<String> {
|
||||
val supportedLocales = LayoutManager.getLayoutMapping(context)
|
||||
|
||||
val perfectMatch = supportedLocales.keys.find { it.language == locale.language && it.country == locale.country }
|
||||
val languageMatch = supportedLocales.keys.find { it.language == locale.language }
|
||||
@ -242,7 +240,7 @@ object Subtypes {
|
||||
|
||||
for(i in 0 until locales.size()) {
|
||||
val locale = locales.get(i).stripExtensionsIfNeeded()
|
||||
val layout = findClosestLocaleLayouts(locale).firstOrNull() ?: continue
|
||||
val layout = findClosestLocaleLayouts(context, locale).firstOrNull() ?: continue
|
||||
|
||||
val value = subtypeToString(
|
||||
InputMethodSubtypeBuilder()
|
||||
|
@ -67,22 +67,17 @@ fun KeyboardViewCompose(keyboard: Keyboard?, width: Dp) {
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun KeyboardLayoutPreview(id: String, width: Dp = 172.dp) {
|
||||
fun KeyboardLayoutPreview(id: String, width: Dp = 172.dp, locale: Locale? = null) {
|
||||
val context = LocalContext.current
|
||||
|
||||
val locale = remember(id) {
|
||||
LayoutManager.getLayout(context, id).languages.firstOrNull()?.let {
|
||||
val l = Locale.forLanguageTag(it)
|
||||
|
||||
println("SET LOCALE: $it to $l, ${l.language}, ${l.country}")
|
||||
l
|
||||
val loc = remember(id) {
|
||||
locale ?: LayoutManager.getLayout(context, id).languages.firstOrNull()?.let {
|
||||
Locale.forLanguageTag(it)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
val configuration = LocalConfiguration.current
|
||||
val isLandscape = configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
|
||||
val isLandscape = false//configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
|
||||
|
||||
val widthPx: Int
|
||||
val heightPx: Int
|
||||
@ -116,7 +111,7 @@ fun KeyboardLayoutPreview(id: String, width: Dp = 172.dp) {
|
||||
height = heightPx,
|
||||
gap = 4.0f,
|
||||
keyboardLayoutSet = id,
|
||||
locale = locale ?: Locale.ENGLISH,
|
||||
locale = loc ?: Locale.ENGLISH,
|
||||
editorInfo = editorInfo,
|
||||
numberRow = numberRow,
|
||||
useSplitLayout = isLandscape,
|
||||
|
@ -130,19 +130,15 @@ private fun levenshteinDistance(lhs: CharSequence, rhs: CharSequence): Int {
|
||||
return cost[lhsLen]
|
||||
}
|
||||
|
||||
private fun <T> List<T>.search(searchTarget: String, keyFunction: (T) -> String): List<T> {
|
||||
val maxDistance = searchTarget.length * 2 / 3
|
||||
fun <T> List<T>.searchMultiple(searchTarget: String, maxDistance: Int = searchTarget.length * 2 / 3, limitLength: Boolean = false, keyFunction: (T) -> List<String>): List<T> {
|
||||
return this.mapNotNull { item ->
|
||||
val key = keyFunction(item)
|
||||
val distance = levenshteinDistance(searchTarget, key)
|
||||
if (distance <= maxDistance) Pair(item, distance) else null
|
||||
}.sortedBy { it.second }.map { it.first }
|
||||
}
|
||||
|
||||
private fun <T> List<T>.searchMultiple(searchTarget: String, keyFunction: (T) -> List<String>): List<T> {
|
||||
val maxDistance = searchTarget.length * 2 / 3
|
||||
return this.mapNotNull { item ->
|
||||
val keys = keyFunction(item)
|
||||
val keys = keyFunction(item).let {
|
||||
if(limitLength) {
|
||||
it.map { it.substring(0 until searchTarget.length.coerceAtMost(it.length)) }
|
||||
} else {
|
||||
it
|
||||
}
|
||||
}
|
||||
val minDistanceKey = keys.minByOrNull { levenshteinDistance(searchTarget, it) }
|
||||
val minDistance = minDistanceKey?.let { levenshteinDistance(searchTarget, it) }
|
||||
if (minDistance != null && minDistance <= maxDistance) Pair(item, minDistance) else null
|
||||
|
@ -12,7 +12,6 @@ import androidx.navigation.compose.rememberNavController
|
||||
import org.futo.inputmethod.latin.R
|
||||
import org.futo.inputmethod.latin.uix.ErrorDialog
|
||||
import org.futo.inputmethod.latin.uix.InfoDialog
|
||||
import org.futo.inputmethod.latin.uix.settings.pages.AddLanguageScreen
|
||||
import org.futo.inputmethod.latin.uix.settings.pages.AdvancedParametersScreen
|
||||
import org.futo.inputmethod.latin.uix.settings.pages.BlacklistScreen
|
||||
import org.futo.inputmethod.latin.uix.settings.pages.CreditsScreen
|
||||
@ -25,6 +24,8 @@ import org.futo.inputmethod.latin.uix.settings.pages.LanguagesScreen
|
||||
import org.futo.inputmethod.latin.uix.settings.pages.PaymentScreen
|
||||
import org.futo.inputmethod.latin.uix.settings.pages.PaymentThankYouScreen
|
||||
import org.futo.inputmethod.latin.uix.settings.pages.PredictiveTextScreen
|
||||
import org.futo.inputmethod.latin.uix.settings.pages.SelectLanguageScreen
|
||||
import org.futo.inputmethod.latin.uix.settings.pages.SelectLayoutsScreen
|
||||
import org.futo.inputmethod.latin.uix.settings.pages.ThemeScreen
|
||||
import org.futo.inputmethod.latin.uix.settings.pages.VoiceInputScreen
|
||||
import org.futo.inputmethod.latin.uix.settings.pages.addModelManagerNavigation
|
||||
@ -53,8 +54,8 @@ fun SettingsNavigator(
|
||||
) {
|
||||
composable("home") { HomeScreen(navController) }
|
||||
composable("languages") { LanguagesScreen(navController) }
|
||||
composable("addLanguage") { AddLanguageScreen(navController) }
|
||||
composable("addLayout/{lang}") { AddLanguageScreen(navController, it.arguments?.getString("lang")?.urlDecode()) }
|
||||
composable("addLanguage") { SelectLanguageScreen(navController) }
|
||||
composable("addLayout/{lang}") { SelectLayoutsScreen(navController, it.arguments?.getString("lang")?.urlDecode() ?: "") }
|
||||
composable("predictiveText") { PredictiveTextScreen(navController) }
|
||||
composable("advancedparams") { AdvancedParametersScreen(navController) }
|
||||
addTypingNavigation(navController)
|
||||
@ -87,8 +88,4 @@ fun SettingsNavigator(
|
||||
}
|
||||
addModelManagerNavigation(navController)
|
||||
}
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
navController.navigate("devlayouts")
|
||||
}
|
||||
}
|
@ -1,173 +1,184 @@
|
||||
package org.futo.inputmethod.latin.uix.settings.pages
|
||||
|
||||
import androidx.compose.foundation.border
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.foundation.text.BasicTextField
|
||||
import androidx.compose.foundation.text.KeyboardOptions
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Search
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.SolidColor
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.input.PlatformImeOptions
|
||||
import androidx.compose.ui.text.input.TextFieldValue
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.navigation.NavHostController
|
||||
import androidx.navigation.compose.rememberNavController
|
||||
import org.futo.inputmethod.latin.Subtypes
|
||||
import org.futo.inputmethod.latin.stripExtensionsIfNeeded
|
||||
import org.futo.inputmethod.latin.uix.settings.DropDownPicker
|
||||
import org.futo.inputmethod.latin.uix.KeyboardLayoutPreview
|
||||
import org.futo.inputmethod.latin.uix.actions.searchMultiple
|
||||
import org.futo.inputmethod.latin.uix.settings.NavigationItem
|
||||
import org.futo.inputmethod.latin.uix.settings.NavigationItemStyle
|
||||
import org.futo.inputmethod.latin.uix.settings.ScreenTitle
|
||||
import org.futo.inputmethod.latin.uix.settings.ScrollableList
|
||||
import org.futo.inputmethod.latin.uix.settings.SettingItem
|
||||
import org.futo.inputmethod.latin.uix.urlEncode
|
||||
import org.futo.inputmethod.v2keyboard.LayoutManager
|
||||
import java.text.Normalizer
|
||||
import java.util.Locale
|
||||
|
||||
val QwertyVariants = listOf("qwerty", "qwertz", "dvorak", "azerty", "colemak", "bepo", "pcqwerty", "nordic")
|
||||
|
||||
fun makeQwertyWithPrimary(primary: String): List<String> {
|
||||
return listOf(primary) + QwertyVariants.filter { it != primary }
|
||||
private val alphaRegex = Regex("[^a-zA-Z\\s]")
|
||||
fun normalize(str: String): String {
|
||||
return Normalizer.normalize(str, Normalizer.Form.NFD)
|
||||
.replace(alphaRegex, "")
|
||||
}
|
||||
|
||||
fun makeQwertyWithPrimary(primary: String, secondary: String): List<String> {
|
||||
return listOf(primary, secondary) + QwertyVariants.filter { it != primary && it != secondary }
|
||||
}
|
||||
|
||||
|
||||
val LocaleLayoutMap = mapOf(
|
||||
"af" to QwertyVariants,
|
||||
"ar" to listOf("arabic"),
|
||||
"az_AZ" to QwertyVariants,
|
||||
"be_BY" to listOf("east_slavic", "east_slavic_phonetic"),
|
||||
"bg" to listOf("bulgarian", "bulgarian_bds"),
|
||||
"bn_BD" to listOf("bengali_akkhor"),
|
||||
"bn_IN" to listOf("bengali"),
|
||||
"ca" to makeQwertyWithPrimary("spanish"),
|
||||
"cs" to makeQwertyWithPrimary("qwertz"),
|
||||
"da" to makeQwertyWithPrimary("nordic"),
|
||||
"de" to makeQwertyWithPrimary("qwertz"),
|
||||
"de_CH" to makeQwertyWithPrimary("swiss"),
|
||||
"el" to makeQwertyWithPrimary("greek"),
|
||||
"en_IN" to QwertyVariants,
|
||||
"en_US" to QwertyVariants,
|
||||
"en_GB" to QwertyVariants,
|
||||
"eo" to makeQwertyWithPrimary("spanish"),
|
||||
"es" to makeQwertyWithPrimary("spanish"),
|
||||
"es_US" to makeQwertyWithPrimary("spanish"),
|
||||
"es_419" to makeQwertyWithPrimary("spanish"),
|
||||
"et_EE" to makeQwertyWithPrimary("nordic"),
|
||||
"eu_ES" to makeQwertyWithPrimary("spanish"),
|
||||
"fa" to listOf("farsi"),
|
||||
"ckb" to listOf("kurdish"),
|
||||
"fi" to makeQwertyWithPrimary("nordic"),
|
||||
"fr" to makeQwertyWithPrimary("azerty", "swiss"),
|
||||
"fr_CA" to makeQwertyWithPrimary("qwerty", "swiss"),
|
||||
"fr_CH" to makeQwertyWithPrimary("swiss"),
|
||||
"gl_ES" to makeQwertyWithPrimary("spanish"),
|
||||
"hi" to listOf("hindi", "hindi_compact"),
|
||||
//"hi_ZZ" to QwertyVariants,
|
||||
"hr" to makeQwertyWithPrimary("qwertz"),
|
||||
"hu" to makeQwertyWithPrimary("qwertz"),
|
||||
"hy_AM" to listOf("armenian_phonetic"),
|
||||
"in" to QwertyVariants,
|
||||
"is" to QwertyVariants,
|
||||
"it" to QwertyVariants,
|
||||
"it_CH" to makeQwertyWithPrimary("swiss"),
|
||||
"iw" to listOf("hebrew"),
|
||||
"ka_GE" to listOf("georgian"),
|
||||
"kk" to listOf("east_slavic", "east_slavic_phonetic"),
|
||||
"km_KH" to listOf("khmer"),
|
||||
"kn_IN" to listOf("kannada"),
|
||||
"ky" to listOf("east_slavic", "east_slavic_phonetic"),
|
||||
"lo_LA" to listOf("lao"),
|
||||
"lt" to QwertyVariants,
|
||||
"lv" to QwertyVariants,
|
||||
"mk" to listOf("south_slavic"),
|
||||
"ml_IN" to listOf("malayalam"),
|
||||
"mn_MN" to listOf("mongolian"),
|
||||
"mr_IN" to listOf("marathi"),
|
||||
"ms_MY" to QwertyVariants,
|
||||
"nb" to listOf("nordic"),
|
||||
"ne_NP" to listOf("nepali_romanized", "nepali_traditional"),
|
||||
"nl" to QwertyVariants,
|
||||
"nl_BE" to makeQwertyWithPrimary("azerty"),
|
||||
"pl" to QwertyVariants,
|
||||
"pt_BR" to QwertyVariants,
|
||||
"pt_PT" to QwertyVariants,
|
||||
"ro" to QwertyVariants,
|
||||
"ru" to listOf("east_slavic", "east_slavic_phonetic"),
|
||||
"si_LK" to listOf("sinhala"),
|
||||
"sk" to QwertyVariants,
|
||||
"sl" to QwertyVariants,
|
||||
"sr" to listOf("south_slavic"),
|
||||
"sr_ZZ" to listOf("serbian_qwertz"),
|
||||
"sv" to listOf("nordic"),
|
||||
"sw" to QwertyVariants,
|
||||
"ta_IN" to listOf("tamil"),
|
||||
"ta_LK" to listOf("tamil"),
|
||||
"ta_SG" to listOf("tamil"),
|
||||
"te_IN" to listOf("telugu"),
|
||||
"th" to listOf("thai"),
|
||||
"tl" to makeQwertyWithPrimary("spanish"),
|
||||
"tr" to makeQwertyWithPrimary("turkish"),
|
||||
"uk" to listOf("east_slavic", "east_slavic_phonetic"),
|
||||
"uz_UZ" to listOf("uzbek"),
|
||||
"vi" to QwertyVariants,
|
||||
"zu" to QwertyVariants,
|
||||
"zz" to QwertyVariants,
|
||||
)
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun AddLanguageScreen(navController: NavHostController = rememberNavController(), defaultLocale: String? = null) {
|
||||
fun SelectLanguageScreen(navController: NavHostController = rememberNavController()) {
|
||||
val context = LocalContext.current
|
||||
|
||||
val defaultLocaleVal = defaultLocale ?: context.resources.configuration.locale.stripExtensionsIfNeeded().toString()
|
||||
val defaultLayout = Subtypes.findClosestLocaleLayouts(Subtypes.getLocale(defaultLocaleVal)).firstOrNull() ?: "qwerty"
|
||||
val layoutMapping = remember { LayoutManager.getLayoutMapping(context) }
|
||||
|
||||
val selectedLocale: MutableState<String> = remember { mutableStateOf(defaultLocale ?: context.resources.configuration.locale.stripExtensionsIfNeeded().toString()) }
|
||||
val selectedLayout: MutableState<String> = remember { mutableStateOf(defaultLayout) }
|
||||
val systemLocale = remember { context.resources.configuration.locales[0] }
|
||||
val textFieldValue = remember { mutableStateOf(TextFieldValue("")) }
|
||||
|
||||
val locales = remember {
|
||||
layoutMapping.keys.toList().sortedBy {
|
||||
it.getDisplayName(systemLocale)
|
||||
}
|
||||
}
|
||||
|
||||
val searchKeys = if(textFieldValue.value.text.isEmpty()) {
|
||||
locales
|
||||
} else {
|
||||
locales.searchMultiple(textFieldValue.value.text.lowercase(), limitLength = true, maxDistance = Int.MAX_VALUE) {
|
||||
listOf(
|
||||
it.language, it.getDisplayName(systemLocale), it.getDisplayName(it)
|
||||
).map { normalize(it.lowercase()) }.flatMap { it.split(" ") }.filter { it.isNotBlank() }
|
||||
}
|
||||
}
|
||||
|
||||
LazyColumn {
|
||||
item {
|
||||
ScreenTitle("Select language to add", showBack = true, navController)
|
||||
}
|
||||
|
||||
item {
|
||||
Surface(color = MaterialTheme.colorScheme.surfaceContainerHighest, shape = RoundedCornerShape(8.dp), modifier = Modifier.padding(8.dp).height(48.dp).fillMaxWidth()) {
|
||||
Row(modifier = Modifier.padding(8.dp), verticalAlignment = Alignment.CenterVertically) {
|
||||
Icon(Icons.Default.Search, contentDescription = "Search")
|
||||
Spacer(modifier = Modifier.width(8.dp))
|
||||
BasicTextField(
|
||||
value = textFieldValue.value,
|
||||
onValueChange = { textFieldValue.value = it },
|
||||
keyboardOptions = KeyboardOptions.Default.copy(
|
||||
platformImeOptions = PlatformImeOptions(
|
||||
privateImeOptions = "org.futo.inputmethod.latin.NoSuggestions=1,org.futo.inputmethod.latin.ForceLayout=qwerty,org.futo.inputmethod.latin.ForceLocale=zz"
|
||||
)
|
||||
),
|
||||
modifier = Modifier.weight(1.0f),
|
||||
cursorBrush = SolidColor(MaterialTheme.colorScheme.onSurface),
|
||||
textStyle = TextStyle.Default.copy(color = MaterialTheme.colorScheme.onSurface)
|
||||
)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
items(searchKeys) {
|
||||
NavigationItem(
|
||||
title = it.getDisplayName(systemLocale),
|
||||
subtitle = it.getDisplayName(it),
|
||||
style = NavigationItemStyle.MiscNoArrow,
|
||||
navigate = {
|
||||
navController.navigate("addLayout/" + it.toLanguageTag().urlEncode())
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Composable
|
||||
fun LayoutPreview(name: String, locale: Locale, onClick: () -> Unit) {
|
||||
val context = LocalContext.current
|
||||
val layoutName = remember { LayoutManager.getLayout(context, name).name }
|
||||
|
||||
Box(
|
||||
Modifier.padding(4.dp).fillMaxWidth().border(
|
||||
1.dp,
|
||||
MaterialTheme.colorScheme.outlineVariant,
|
||||
RoundedCornerShape(8.dp)
|
||||
).clickable { onClick() }) {
|
||||
Column(
|
||||
modifier = Modifier.fillMaxWidth().padding(8.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
KeyboardLayoutPreview(id = name, width = 172.dp, locale = locale)
|
||||
|
||||
Text(
|
||||
layoutName,
|
||||
style = TextSmallStyle,
|
||||
modifier = Modifier.padding(4.dp),
|
||||
textAlign = TextAlign.Center
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun SelectLayoutsScreen(navController: NavHostController = rememberNavController(), language: String = "en_US") {
|
||||
val context = LocalContext.current
|
||||
|
||||
val locale = remember { Locale.forLanguageTag(language.replace("_", "-")) }
|
||||
|
||||
val layoutMapping = remember { LayoutManager.getLayoutMapping(context) }
|
||||
|
||||
val systemLocale = remember { context.resources.configuration.locales[0] }
|
||||
|
||||
val relevantLayouts = remember {
|
||||
layoutMapping.entries.filter {
|
||||
it.key.language == locale.language
|
||||
}.flatMap { it.value }.toSet()
|
||||
}
|
||||
|
||||
val keys = remember { LocaleLayoutMap.keys.toList() }
|
||||
ScrollableList {
|
||||
ScreenTitle("Add Language", showBack = true, navController)
|
||||
ScreenTitle(locale.getDisplayName(locale), showBack = true, navController)
|
||||
|
||||
SettingItem(title = "Language") {
|
||||
DropDownPicker(
|
||||
"",
|
||||
keys,
|
||||
selectedLocale.value,
|
||||
{
|
||||
selectedLocale.value = it
|
||||
selectedLayout.value = LocaleLayoutMap[it]!!.first()
|
||||
},
|
||||
{
|
||||
Subtypes.getNameForLocale(it)
|
||||
},
|
||||
modifier = Modifier.width(180.dp)
|
||||
)
|
||||
}
|
||||
ScreenTitle("Select a layout to add")
|
||||
|
||||
SettingItem(title = "Layout") {
|
||||
DropDownPicker(
|
||||
"",
|
||||
LocaleLayoutMap[selectedLocale.value] ?: listOf(),
|
||||
selectedLayout.value,
|
||||
{ selectedLayout.value = it },
|
||||
{ Subtypes.getLayoutName(context, it) },
|
||||
modifier = Modifier.width(180.dp)
|
||||
)
|
||||
}
|
||||
relevantLayouts.forEach {
|
||||
LayoutPreview(it, locale) {
|
||||
Subtypes.addLanguage(context, locale, it)
|
||||
|
||||
Button(onClick = {
|
||||
Subtypes.addLanguage(
|
||||
context,
|
||||
Subtypes.getLocale(selectedLocale.value),
|
||||
selectedLayout.value
|
||||
)
|
||||
|
||||
navController.navigateUp()
|
||||
}, modifier = Modifier.fillMaxWidth().padding(16.dp)) {
|
||||
Text("Add")
|
||||
// Go back to languages
|
||||
for(x in 0 until 3) navController.navigateUp()
|
||||
navController.navigate("languages")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -6,13 +6,20 @@ import android.util.Log
|
||||
import com.charleskorn.kaml.PolymorphismStyle
|
||||
import com.charleskorn.kaml.Yaml
|
||||
import com.charleskorn.kaml.YamlConfiguration
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.modules.EmptySerializersModule
|
||||
import org.futo.inputmethod.latin.uix.actions.BugInfo
|
||||
import org.futo.inputmethod.latin.uix.actions.BugViewerState
|
||||
import java.util.Locale
|
||||
|
||||
@Serializable
|
||||
data class Mappings(
|
||||
val languages: Map<String, List<String>>
|
||||
)
|
||||
|
||||
object LayoutManager {
|
||||
private var layoutsById: Map<String, Keyboard>? = null
|
||||
private var localeToLayoutsMappings: Map<Locale, List<String>>? = null
|
||||
private var initialized = false
|
||||
|
||||
private fun listFilesRecursively(assetManager: AssetManager, path: String): List<String> {
|
||||
@ -26,7 +33,7 @@ object LayoutManager {
|
||||
|
||||
private fun getAllLayoutPaths(assetManager: AssetManager): List<String> {
|
||||
return listFilesRecursively(assetManager, "layouts").filter {
|
||||
it.endsWith(".yml") || it.endsWith(".yaml")
|
||||
(it.endsWith(".yml") || it.endsWith(".yaml")) && it != "mapping.yaml"
|
||||
}
|
||||
}
|
||||
|
||||
@ -35,6 +42,10 @@ object LayoutManager {
|
||||
|
||||
initialized = true
|
||||
|
||||
localeToLayoutsMappings = parseMappings(context, "layouts/mapping.yaml").languages.mapKeys {
|
||||
Locale.forLanguageTag(it.key.replace("_", "-"))
|
||||
}
|
||||
|
||||
val assetManager = context.assets
|
||||
|
||||
val layoutPaths = getAllLayoutPaths(assetManager)
|
||||
@ -65,10 +76,10 @@ object LayoutManager {
|
||||
return layoutsById?.get(name) ?: throw IllegalArgumentException("Failed to find keyboard layout $name. Available layouts: ${layoutsById?.keys}")
|
||||
}
|
||||
|
||||
fun queryLayoutsForLocale(locale: Locale): List<Keyboard> {
|
||||
val language = locale.language
|
||||
//val script = locale.getKeyboardScript()
|
||||
return layoutsById!!.values.filter { it.languages.contains(language) }
|
||||
fun getLayoutMapping(context: Context): Map<Locale, List<String>> {
|
||||
init(context)
|
||||
|
||||
return localeToLayoutsMappings!!
|
||||
}
|
||||
|
||||
fun getAllLayoutNames(context: Context): List<String> {
|
||||
@ -80,6 +91,20 @@ object LayoutManager {
|
||||
}
|
||||
}
|
||||
|
||||
private fun parseMappings(context: Context, mappingsPath: String): Mappings {
|
||||
val yaml = Yaml(
|
||||
EmptySerializersModule(),
|
||||
YamlConfiguration(
|
||||
polymorphismStyle = PolymorphismStyle.Property,
|
||||
allowAnchorsAndAliases = true
|
||||
)
|
||||
)
|
||||
return context.assets.open(mappingsPath).use { inputStream ->
|
||||
val yamlString = inputStream.bufferedReader().use { it.readText() }
|
||||
|
||||
yaml.decodeFromString(Mappings.serializer(), yamlString)
|
||||
}
|
||||
}
|
||||
|
||||
private fun parseKeyboardYaml(context: Context, layoutPath: String): Keyboard {
|
||||
val yaml = Yaml(
|
||||
|
@ -1,6 +1,5 @@
|
||||
package org.futo.inputmethod.v2keyboard
|
||||
|
||||
import org.futo.inputmethod.keyboard.internal.KeyboardLayoutKind
|
||||
import org.futo.inputmethod.latin.common.Constants
|
||||
|
||||
fun getDefaultMoreKeysForKey(code: Int, relevantSpecShortcut: List<String>?): String {
|
||||
|
Loading…
Reference in New Issue
Block a user