make subtypeDialog survive screen rotation (but currently loses changes to settings)

This commit is contained in:
Helium314 2025-02-25 22:32:05 +01:00
parent 93e6f88f6c
commit cab9cc7de0
6 changed files with 33 additions and 23 deletions

View file

@ -206,7 +206,7 @@ class LanguageSettingsDialog(
infos.remove(subtype) infos.remove(subtype)
//if (isCustom) //if (isCustom)
// LayoutUtilsCustom.removeCustomLayoutFile(layoutSetName, context) // LayoutUtilsCustom.removeCustomLayoutFile(layoutSetName, context)
SubtypeUtilsAdditional.removeAdditionalSubtype(prefs, subtype.subtype) SubtypeUtilsAdditional.removeAdditionalSubtype(context, subtype.subtype)
SubtypeSettings.removeEnabledSubtype(context, subtype.subtype) SubtypeSettings.removeEnabledSubtype(context, subtype.subtype)
reloadSetting() reloadSetting()
} }

View file

@ -109,6 +109,10 @@ fun createDictionaryTextHtml(message: String, locale: Locale, context: Context):
@Composable @Composable
fun MissingDictionaryDialog(onDismissRequest: () -> Unit, locale: Locale) { fun MissingDictionaryDialog(onDismissRequest: () -> Unit, locale: Locale) {
val prefs = LocalContext.current.prefs() val prefs = LocalContext.current.prefs()
if (prefs.getBoolean(Settings.PREF_DONT_SHOW_MISSING_DICTIONARY_DIALOG, Defaults.PREF_DONT_SHOW_MISSING_DICTIONARY_DIALOG)) {
onDismissRequest()
return
}
val availableDicts = createDictionaryTextAnnotated(locale) val availableDicts = createDictionaryTextAnnotated(locale)
val dictLink = "${Links.DICTIONARY_URL}/src/branch/main/dictionaries/main_$locale.dict" val dictLink = "${Links.DICTIONARY_URL}/src/branch/main/dictionaries/main_$locale.dict"
val message = stringResource(R.string.no_dictionary_message, "§repl1§", locale.toString(), "§repl2§") val message = stringResource(R.string.no_dictionary_message, "§repl1§", locale.toString(), "§repl2§")

View file

@ -127,7 +127,7 @@ data class SettingsSubtype(val locale: Locale, val extraValues: String) {
fun with(extraValueKey: String, extraValue: String?): SettingsSubtype { fun with(extraValueKey: String, extraValue: String?): SettingsSubtype {
val newList = extraValues.split(",") val newList = extraValues.split(",")
.filterNot { it.startsWith("$extraValueKey=") || it == extraValueKey } .filterNot { it.isBlank() || it.startsWith("$extraValueKey=") || it == extraValueKey }
val newValue = if (extraValue == null) extraValueKey else "$extraValueKey=$extraValue" val newValue = if (extraValue == null) extraValueKey else "$extraValueKey=$extraValue"
val newValues = (newList + newValue).joinToString(",") val newValues = (newList + newValue).joinToString(",")
return copy(extraValues = newValues) return copy(extraValues = newValues)
@ -135,7 +135,7 @@ data class SettingsSubtype(val locale: Locale, val extraValues: String) {
fun without(extraValueKey: String): SettingsSubtype { fun without(extraValueKey: String): SettingsSubtype {
val newValues = extraValues.split(",") val newValues = extraValues.split(",")
.filterNot { it.startsWith("$extraValueKey=") || it == extraValueKey } .filterNot { it.isBlank() || it.startsWith("$extraValueKey=") || it == extraValueKey }
.joinToString(",") .joinToString(",")
return copy(extraValues = newValues) return copy(extraValues = newValues)
} }
@ -174,7 +174,8 @@ data class SettingsSubtype(val locale: Locale, val extraValues: String) {
Log.e(SettingsSubtype::class.simpleName, "unknown language, should not happen ${locale}, $languageTag, $extraValue, ${hashCode()}, $nameResId") Log.e(SettingsSubtype::class.simpleName, "unknown language, should not happen ${locale}, $languageTag, $extraValue, ${hashCode()}, $nameResId")
} }
val filteredExtraValue = extraValue.split(",").filterNot { val filteredExtraValue = extraValue.split(",").filterNot {
it == ExtraValue.ASCII_CAPABLE it.isBlank()
|| it == ExtraValue.ASCII_CAPABLE
|| it == ExtraValue.EMOJI_CAPABLE || it == ExtraValue.EMOJI_CAPABLE
|| it == ExtraValue.IS_ADDITIONAL_SUBTYPE || it == ExtraValue.IS_ADDITIONAL_SUBTYPE
|| it.startsWith(ExtraValue.UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME) || it.startsWith(ExtraValue.UNTRANSLATABLE_STRING_IN_SUBTYPE_NAME)

View file

@ -58,7 +58,10 @@ object SubtypeUtilsAdditional {
Settings.writePrefAdditionalSubtypes(prefs, newAdditionalSubtypesString) Settings.writePrefAdditionalSubtypes(prefs, newAdditionalSubtypesString)
} }
fun removeAdditionalSubtype(prefs: SharedPreferences, subtype: InputMethodSubtype) { // todo: SettingsSubtype?
fun removeAdditionalSubtype(context: Context, subtype: InputMethodSubtype) {
val prefs = context.prefs()
SubtypeSettings.removeEnabledSubtype(context, subtype)
val oldAdditionalSubtypesString = prefs.getString(Settings.PREF_ADDITIONAL_SUBTYPES, Defaults.PREF_ADDITIONAL_SUBTYPES)!! val oldAdditionalSubtypesString = prefs.getString(Settings.PREF_ADDITIONAL_SUBTYPES, Defaults.PREF_ADDITIONAL_SUBTYPES)!!
val oldAdditionalSubtypes = createAdditionalSubtypes(oldAdditionalSubtypesString) val oldAdditionalSubtypes = createAdditionalSubtypes(oldAdditionalSubtypesString)
val newAdditionalSubtypes = oldAdditionalSubtypes.filter { it != subtype } val newAdditionalSubtypes = oldAdditionalSubtypes.filter { it != subtype }

View file

@ -2,7 +2,6 @@
package helium314.keyboard.settings.dialogs package helium314.keyboard.settings.dialogs
import android.content.Context import android.content.Context
import android.view.inputmethod.InputMethodSubtype
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
@ -77,12 +76,10 @@ import helium314.keyboard.settings.layoutIntent
import helium314.keyboard.settings.screens.GetIcon import helium314.keyboard.settings.screens.GetIcon
import java.util.Locale import java.util.Locale
// todo:
// rotating closes the dialog
@Composable @Composable
fun SubtypeDialog( fun SubtypeDialog(
onDismissRequest: () -> Unit, onDismissRequest: () -> Unit,
subtype: InputMethodSubtype, initialSubtype: SettingsSubtype,
onConfirmed: (SettingsSubtype) -> Unit, onConfirmed: (SettingsSubtype) -> Unit,
) { ) {
// todo: make sure the values are always correct (e.g. if using rememberSaveable and rotating) // todo: make sure the values are always correct (e.g. if using rememberSaveable and rotating)
@ -91,7 +88,7 @@ fun SubtypeDialog(
val b = (LocalContext.current.getActivity() as? SettingsActivity)?.prefChanged?.collectAsState() val b = (LocalContext.current.getActivity() as? SettingsActivity)?.prefChanged?.collectAsState()
if ((b?.value ?: 0) < 0) if ((b?.value ?: 0) < 0)
Log.v("irrelevant", "stupid way to trigger recomposition on preference change") Log.v("irrelevant", "stupid way to trigger recomposition on preference change")
var currentSubtype by remember { mutableStateOf(subtype.toSettingsSubtype()) } var currentSubtype by remember { mutableStateOf(initialSubtype) }
val availableLocalesForScript = getAvailableSecondaryLocales(ctx, currentSubtype.locale).sortedBy { it.toLanguageTag() } val availableLocalesForScript = getAvailableSecondaryLocales(ctx, currentSubtype.locale).sortedBy { it.toLanguageTag() }
var showSecondaryLocaleDialog by remember { mutableStateOf(false) } var showSecondaryLocaleDialog by remember { mutableStateOf(false) }
var showKeyOrderDialog by remember { mutableStateOf(false) } var showKeyOrderDialog by remember { mutableStateOf(false) }
@ -102,19 +99,22 @@ fun SubtypeDialog(
ThreeButtonAlertDialog( ThreeButtonAlertDialog(
onDismissRequest = onDismissRequest, onDismissRequest = onDismissRequest,
onConfirmed = { onConfirmed(currentSubtype) }, onConfirmed = { onConfirmed(currentSubtype) },
neutralButtonText = if (SubtypeSettings.isAdditionalSubtype(subtype)) stringResource(R.string.delete) else null, neutralButtonText = if (initialSubtype.isAdditionalSubtype(prefs)) stringResource(R.string.delete) else null,
onNeutral = { onNeutral = {
SubtypeUtilsAdditional.removeAdditionalSubtype(ctx, initialSubtype.toAdditionalSubtype()!!)
SubtypeSettings.removeEnabledSubtype(ctx, initialSubtype.toAdditionalSubtype()!!)
onDismissRequest() onDismissRequest()
SubtypeUtilsAdditional.removeAdditionalSubtype(prefs, subtype)
SubtypeSettings.removeEnabledSubtype(ctx, subtype)
}, },
title = { Text(SubtypeLocaleUtils.getSubtypeDisplayNameInSystemLocale(subtype)) }, title = {
val mainLayout = initialSubtype.mainLayoutName() ?: SubtypeLocaleUtils.QWERTY
Text(SubtypeLocaleUtils.getDisplayNameInSystemLocale(mainLayout, initialSubtype.locale))
},
content = { content = {
Column( Column(
modifier = Modifier.verticalScroll(scrollState), modifier = Modifier.verticalScroll(scrollState),
verticalArrangement = Arrangement.spacedBy(8.dp), verticalArrangement = Arrangement.spacedBy(8.dp),
) { ) {
MainLayoutRow(subtype, currentSubtype, customMainLayouts) { currentSubtype = it } MainLayoutRow(initialSubtype, currentSubtype, customMainLayouts) { currentSubtype = it }
if (availableLocalesForScript.size > 1) { if (availableLocalesForScript.size > 1) {
WithSmallTitle(stringResource(R.string.secondary_locale)) { WithSmallTitle(stringResource(R.string.secondary_locale)) {
TextButton(onClick = { showSecondaryLocaleDialog = true }) { TextButton(onClick = { showSecondaryLocaleDialog = true }) {
@ -306,7 +306,7 @@ private fun PopupOrderDialog(
@Composable @Composable
private fun MainLayoutRow( private fun MainLayoutRow(
subtype: InputMethodSubtype, initialSubtype: SettingsSubtype,
currentSubtype: SettingsSubtype, currentSubtype: SettingsSubtype,
customLayouts: List<String>, customLayouts: List<String>,
setCurrentSubtype: (SettingsSubtype) -> Unit, setCurrentSubtype: (SettingsSubtype) -> Unit,
@ -339,12 +339,13 @@ private fun MainLayoutRow(
Text(SubtypeLocaleUtils.getDisplayNameInSystemLocale(it, currentSubtype.locale)) Text(SubtypeLocaleUtils.getDisplayNameInSystemLocale(it, currentSubtype.locale))
Row (verticalAlignment = Alignment.CenterVertically) { Row (verticalAlignment = Alignment.CenterVertically) {
Icon(painterResource(R.drawable.ic_edit), stringResource(R.string.edit_layout), Modifier.clickable { showLayoutEditDialog = it to null }) Icon(painterResource(R.drawable.ic_edit), stringResource(R.string.edit_layout), Modifier.clickable { showLayoutEditDialog = it to null })
if (it in customLayouts && subtype.mainLayoutName() != it) // don't allow current main layout if (it in customLayouts && initialSubtype.mainLayoutName() != it) // don't allow current main layout
Icon(painterResource(R.drawable.ic_bin), stringResource(R.string.delete), Modifier.clickable { showLayoutDeleteDialog = true }) Icon(painterResource(R.drawable.ic_bin), stringResource(R.string.delete), Modifier.clickable { showLayoutDeleteDialog = true })
} }
} }
if (showLayoutDeleteDialog) { if (showLayoutDeleteDialog) {
val others = SubtypeSettings.getAdditionalSubtypes().filter { st -> st.mainLayoutName() == it }.any { it != subtype } val others = SubtypeSettings.getAdditionalSubtypes().filter { st -> st.mainLayoutName() == it }
.any { it.toSettingsSubtype() != initialSubtype }
ConfirmationDialog( ConfirmationDialog(
onDismissRequest = { showLayoutDeleteDialog = false }, onDismissRequest = { showLayoutDeleteDialog = false },
confirmButtonText = stringResource(R.string.delete), confirmButtonText = stringResource(R.string.delete),

View file

@ -17,6 +17,7 @@ import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
@ -57,7 +58,7 @@ fun LanguageScreen(
val b = (LocalContext.current.getActivity() as? SettingsActivity)?.prefChanged?.collectAsState() val b = (LocalContext.current.getActivity() as? SettingsActivity)?.prefChanged?.collectAsState()
if ((b?.value ?: 0) < 0) if ((b?.value ?: 0) < 0)
Log.v("irrelevant", "stupid way to trigger recomposition on preference change") Log.v("irrelevant", "stupid way to trigger recomposition on preference change")
var selectedSubtype: InputMethodSubtype? by remember { mutableStateOf(null) } // todo: rememberSaveable? maybe with SettingsSubtype? var selectedSubtype: String? by rememberSaveable { mutableStateOf(null) }
val enabledSubtypes = SubtypeSettings.getEnabledSubtypes(prefs) val enabledSubtypes = SubtypeSettings.getEnabledSubtypes(prefs)
SearchScreen( SearchScreen(
onClickBack = onClickBack, onClickBack = onClickBack,
@ -82,7 +83,7 @@ fun LanguageScreen(
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.clickable { selectedSubtype = item } .clickable { selectedSubtype = item.toSettingsSubtype().toPref() }
.padding(vertical = 6.dp, horizontal = 16.dp) .padding(vertical = 6.dp, horizontal = 16.dp)
) { ) {
var showNoDictDialog by remember { mutableStateOf(false) } var showNoDictDialog by remember { mutableStateOf(false) }
@ -112,16 +113,16 @@ fun LanguageScreen(
} }
) )
if (selectedSubtype != null) { if (selectedSubtype != null) {
val oldSubtype = selectedSubtype!! val oldSubtype = selectedSubtype!!.toSettingsSubtype()
SubtypeDialog( SubtypeDialog(
onDismissRequest = { onDismissRequest = {
selectedSubtype = null selectedSubtype = null
sortedSubtypes = getSortedSubtypes(ctx) sortedSubtypes = getSortedSubtypes(ctx)
}, },
onConfirmed = { onConfirmed = {
SubtypeUtilsAdditional.changeAdditionalSubtype(oldSubtype.toSettingsSubtype(), it, ctx) SubtypeUtilsAdditional.changeAdditionalSubtype(oldSubtype, it, ctx)
}, },
subtype = oldSubtype initialSubtype = oldSubtype
) )
} }
} }