Make settings screens fully usable on Android 15 (#1484)

enable edge to edge in settings for all Android versions to avoid minor glitches and have more consistent appearance
This commit is contained in:
Eran Leshem 2025-04-21 09:06:41 +03:00 committed by GitHub
parent d15a97ccba
commit d9f17733d9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 301 additions and 229 deletions

View file

@ -6,9 +6,14 @@ import androidx.compose.animation.AnimatedVisibility
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ColumnScope import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.ime
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.systemBars
import androidx.compose.foundation.layout.union
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.rememberScrollState
@ -20,6 +25,7 @@ import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton import androidx.compose.material3.IconButton
import androidx.compose.material3.LocalTextStyle import androidx.compose.material3.LocalTextStyle
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Surface import androidx.compose.material3.Surface
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TextField import androidx.compose.material3.TextField
@ -58,36 +64,41 @@ fun SearchSettingsScreen(
content = { content = {
if (content != null) content() if (content != null) content()
else { else {
Column(Modifier.verticalScroll(rememberScrollState())) { Scaffold(contentWindowInsets = WindowInsets.systemBars.union(WindowInsets.ime)) { innerPadding ->
settings.forEach { Column(
if (it is Int) { Modifier.verticalScroll(rememberScrollState())
PreferenceCategory(stringResource(it)) .then(Modifier.padding(bottom = innerPadding.calculateBottomPadding()))
} else { ) {
// this only animates appearing prefs settings.forEach {
// a solution would be using a list(visible to key) if (it is Int) {
AnimatedVisibility(visible = it != null) { PreferenceCategory(stringResource(it))
if (it != null) } else {
SettingsActivity.settingsContainer[it]?.Preference() // this only animates appearing prefs
// a solution would be using a list(visible to key)
AnimatedVisibility(visible = it != null) {
if (it != null)
SettingsActivity.settingsContainer[it]?.Preference()
}
} }
} }
} }
// lazyColumn has janky scroll for a while (not sure why compose gets smoother after a while)
// maybe related to unnecessary recompositions? but even for just displaying text it's there
// didn't manage to improve things with @Immutable list wrapper and other lazy list hints
// so for now: just use "normal" Column
// even though it takes up to ~50% longer to load it's much better UX
// and the missing appear animations could be added
// LazyColumn {
// items(prefs.filterNotNull(), key = { it }) {
// Box(Modifier.animateItem()) {
// if (it is Int)
// PreferenceCategory(stringResource(it))
// else
// SettingsActivity.settingsContainer[it]!!.Preference()
// }
// }
// }
} }
// lazyColumn has janky scroll for a while (not sure why compose gets smoother after a while)
// maybe related to unnecessary recompositions? but even for just displaying text it's there
// didn't manage to improve things with @Immutable list wrapper and other lazy list hints
// so for now: just use "normal" Column
// even though it takes up to ~50% longer to load it's much better UX
// and the missing appear animations could be added
// LazyColumn {
// items(prefs.filterNotNull(), key = { it }) {
// Box(Modifier.animateItem()) {
// if (it is Int)
// PreferenceCategory(stringResource(it))
// else
// SettingsActivity.settingsContainer[it]!!.Preference()
// }
// }
// }
} }
}, },
filteredItems = { SettingsActivity.settingsContainer.filter(it) }, filteredItems = { SettingsActivity.settingsContainer.filter(it) },
@ -195,9 +206,11 @@ fun <T: Any?> SearchScreen(
} }
} else { } else {
val items = filteredItems(searchText.text) val items = filteredItems(searchText.text)
LazyColumn { Scaffold(contentWindowInsets = WindowInsets.systemBars.union(WindowInsets.ime)) { innerPadding ->
items(items) { LazyColumn(contentPadding = PaddingValues.Absolute(bottom = innerPadding.calculateBottomPadding())) {
itemContent(it) items(items) {
itemContent(it)
}
} }
} }
} }

View file

@ -12,7 +12,14 @@ import android.view.WindowInsets.Type
import android.view.inputmethod.EditorInfo import android.view.inputmethod.EditorInfo
import android.view.inputmethod.InputMethodManager import android.view.inputmethod.InputMethodManager
import androidx.activity.ComponentActivity import androidx.activity.ComponentActivity
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.ime
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.systemBars
import androidx.compose.foundation.layout.union
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Surface import androidx.compose.material3.Surface
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.collectAsState import androidx.compose.runtime.collectAsState
@ -20,6 +27,7 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.ComposeView import androidx.compose.ui.platform.ComposeView
import androidx.core.view.ViewCompat import androidx.core.view.ViewCompat
import helium314.keyboard.compat.locale import helium314.keyboard.compat.locale
@ -98,9 +106,11 @@ class SettingsActivity : ComponentActivity(), SharedPreferences.OnSharedPreferen
|| !UncachedInputMethodManagerUtils.isThisImeEnabled(this, imm) || !UncachedInputMethodManagerUtils.isThisImeEnabled(this, imm)
) } ) }
if (spellchecker) if (spellchecker)
Column { // lazy way of implementing spell checker settings Scaffold(contentWindowInsets = WindowInsets.systemBars.union(WindowInsets.ime)) { innerPadding ->
settingsContainer[Settings.PREF_USE_CONTACTS]!!.Preference() Column(Modifier.padding(innerPadding)) { // lazy way of implementing spell checker settings
settingsContainer[Settings.PREF_BLOCK_POTENTIALLY_OFFENSIVE]!!.Preference() settingsContainer[Settings.PREF_USE_CONTACTS]!!.Preference()
settingsContainer[Settings.PREF_BLOCK_POTENTIALLY_OFFENSIVE]!!.Preference()
}
} }
else else
SettingsNavHost(onClickBack = { this.finish() }) SettingsNavHost(onClickBack = { this.finish() })
@ -143,6 +153,8 @@ class SettingsActivity : ComponentActivity(), SharedPreferences.OnSharedPreferen
} }
intent = null intent = null
} }
enableEdgeToEdge()
} }
override fun onStart() { override fun onStart() {

View file

@ -2,8 +2,14 @@
package helium314.keyboard.settings.screens package helium314.keyboard.settings.screens
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.ime
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.systemBars
import androidx.compose.foundation.layout.union
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Surface import androidx.compose.material3.Surface
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
@ -42,59 +48,64 @@ fun MainSettingsScreen(
settings = emptyList(), settings = emptyList(),
) { ) {
val enabledSubtypes = SubtypeSettings.getEnabledSubtypes(true) val enabledSubtypes = SubtypeSettings.getEnabledSubtypes(true)
Column(Modifier.verticalScroll(rememberScrollState())) { Scaffold(contentWindowInsets = WindowInsets.systemBars.union(WindowInsets.ime)) { innerPadding ->
Preference( Column(
name = stringResource(R.string.language_and_layouts_title), Modifier.verticalScroll(rememberScrollState())
description = enabledSubtypes.joinToString(", ") { it.displayName(ctx) }, .then(Modifier.padding(bottom = innerPadding.calculateBottomPadding()))
onClick = onClickLanguage, ) {
icon = R.drawable.ic_settings_languages
) { NextScreenIcon() }
Preference(
name = stringResource(R.string.settings_screen_preferences),
onClick = onClickPreferences,
icon = R.drawable.ic_settings_preferences
) { NextScreenIcon() }
Preference(
name = stringResource(R.string.settings_screen_appearance),
onClick = onClickAppearance,
icon = R.drawable.ic_settings_appearance
) { NextScreenIcon() }
Preference(
name = stringResource(R.string.settings_screen_toolbar),
onClick = onClickToolbar,
icon = R.drawable.ic_settings_toolbar
) { NextScreenIcon() }
if (JniUtils.sHaveGestureLib)
Preference( Preference(
name = stringResource(R.string.settings_screen_gesture), name = stringResource(R.string.language_and_layouts_title),
onClick = onClickGestureTyping, description = enabledSubtypes.joinToString(", ") { it.displayName(ctx) },
icon = R.drawable.ic_settings_gesture onClick = onClickLanguage,
icon = R.drawable.ic_settings_languages
) { NextScreenIcon() } ) { NextScreenIcon() }
Preference( Preference(
name = stringResource(R.string.settings_screen_correction), name = stringResource(R.string.settings_screen_preferences),
onClick = onClickTextCorrection, onClick = onClickPreferences,
icon = R.drawable.ic_settings_correction icon = R.drawable.ic_settings_preferences
) { NextScreenIcon() } ) { NextScreenIcon() }
Preference( Preference(
name = stringResource(R.string.settings_screen_secondary_layouts), name = stringResource(R.string.settings_screen_appearance),
onClick = onClickLayouts, onClick = onClickAppearance,
icon = R.drawable.ic_ime_switcher icon = R.drawable.ic_settings_appearance
) { NextScreenIcon() } ) { NextScreenIcon() }
Preference( Preference(
name = stringResource(R.string.dictionary_settings_category), name = stringResource(R.string.settings_screen_toolbar),
onClick = onClickDictionaries, onClick = onClickToolbar,
icon = R.drawable.ic_dictionary icon = R.drawable.ic_settings_toolbar
) { NextScreenIcon() } ) { NextScreenIcon() }
Preference( if (JniUtils.sHaveGestureLib)
name = stringResource(R.string.settings_screen_advanced), Preference(
onClick = onClickAdvanced, name = stringResource(R.string.settings_screen_gesture),
icon = R.drawable.ic_settings_advanced onClick = onClickGestureTyping,
) { NextScreenIcon() } icon = R.drawable.ic_settings_gesture
Preference( ) { NextScreenIcon() }
name = stringResource(R.string.settings_screen_about), Preference(
onClick = onClickAbout, name = stringResource(R.string.settings_screen_correction),
icon = R.drawable.ic_settings_about onClick = onClickTextCorrection,
) { NextScreenIcon() } icon = R.drawable.ic_settings_correction
) { NextScreenIcon() }
Preference(
name = stringResource(R.string.settings_screen_secondary_layouts),
onClick = onClickLayouts,
icon = R.drawable.ic_ime_switcher
) { NextScreenIcon() }
Preference(
name = stringResource(R.string.dictionary_settings_category),
onClick = onClickDictionaries,
icon = R.drawable.ic_dictionary
) { NextScreenIcon() }
Preference(
name = stringResource(R.string.settings_screen_advanced),
onClick = onClickAdvanced,
icon = R.drawable.ic_settings_advanced
) { NextScreenIcon() }
Preference(
name = stringResource(R.string.settings_screen_about),
onClick = onClickAbout,
icon = R.drawable.ic_settings_about
) { NextScreenIcon() }
}
} }
} }
} }

View file

@ -10,7 +10,9 @@ import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.imePadding
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.systemBarsPadding
import androidx.compose.foundation.layout.wrapContentSize import androidx.compose.foundation.layout.wrapContentSize
import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.ExtendedFloatingActionButton import androidx.compose.material3.ExtendedFloatingActionButton
@ -177,6 +179,7 @@ fun PersonalDictionaryScreen(
text = { Text(stringResource(R.string.user_dict_add_word_button)) }, text = { Text(stringResource(R.string.user_dict_add_word_button)) },
icon = { Icon(painter = painterResource(R.drawable.ic_edit), stringResource(R.string.user_dict_add_word_button)) }, icon = { Icon(painter = painterResource(R.drawable.ic_edit), stringResource(R.string.user_dict_add_word_button)) },
modifier = Modifier.wrapContentSize(Alignment.BottomEnd).padding(all = 12.dp) modifier = Modifier.wrapContentSize(Alignment.BottomEnd).padding(all = 12.dp)
.then(Modifier.systemBarsPadding().imePadding())
) )
} }

View file

@ -4,8 +4,12 @@ import android.content.Context
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.ime
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.systemBars
import androidx.compose.foundation.layout.union
import androidx.compose.foundation.layout.widthIn import androidx.compose.foundation.layout.widthIn
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
@ -13,6 +17,7 @@ import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Surface import androidx.compose.material3.Surface
import androidx.compose.material3.Switch import androidx.compose.material3.Switch
import androidx.compose.material3.Text import androidx.compose.material3.Text
@ -140,163 +145,191 @@ fun SubtypeScreen(
itemContent = { }, itemContent = { },
filteredItems = { emptyList<String>() } filteredItems = { emptyList<String>() }
) { ) {
Column( Scaffold(contentWindowInsets = WindowInsets.systemBars.union(WindowInsets.ime)) { innerPadding ->
modifier = Modifier.verticalScroll(scrollState).padding(horizontal = 12.dp), Column(
verticalArrangement = Arrangement.spacedBy(8.dp), modifier = Modifier.verticalScroll(scrollState).padding(horizontal = 12.dp)
) { .then(Modifier.padding(bottom = innerPadding.calculateBottomPadding())),
MainLayoutRow(currentSubtype, customMainLayouts) { setCurrentSubtype(it) } verticalArrangement = Arrangement.spacedBy(8.dp),
if (availableLocalesForScript.size > 1) { ) {
WithSmallTitle(stringResource(R.string.secondary_locale)) { MainLayoutRow(currentSubtype, customMainLayouts) { setCurrentSubtype(it) }
TextButton(onClick = { showSecondaryLocaleDialog = true }) { if (availableLocalesForScript.size > 1) {
val text = getSecondaryLocales(currentSubtype.extraValues).joinToString(", ") { WithSmallTitle(stringResource(R.string.secondary_locale)) {
it.localizedDisplayName(ctx) TextButton(onClick = { showSecondaryLocaleDialog = true }) {
}.ifEmpty { stringResource(R.string.action_none) } val text = getSecondaryLocales(currentSubtype.extraValues).joinToString(", ") {
Text(text, Modifier.fillMaxWidth()) it.localizedDisplayName(ctx)
} }.ifEmpty { stringResource(R.string.action_none) }
} Text(text, Modifier.fillMaxWidth())
}
Row {
TextButton(onClick = { showKeyOrderDialog = true }, Modifier.weight(1f))
{ Text(stringResource(R.string.popup_order)) }
DefaultButton(currentSubtype.getExtraValueOf(ExtraValue.POPUP_ORDER) == null) {
setCurrentSubtype(currentSubtype.without(ExtraValue.POPUP_ORDER))
}
}
Row {
TextButton(onClick = { showHintOrderDialog = true }, Modifier.weight(1f))
{ Text(stringResource(R.string.hint_source)) }
DefaultButton(currentSubtype.getExtraValueOf(ExtraValue.HINT_ORDER) == null) {
setCurrentSubtype(currentSubtype.without(ExtraValue.HINT_ORDER))
}
}
if (currentSubtype.locale.script() == ScriptUtils.SCRIPT_LATIN) {
WithSmallTitle(stringResource(R.string.show_popup_keys_title)) {
val explicitValue = currentSubtype.getExtraValueOf(ExtraValue.MORE_POPUPS)
val value = explicitValue ?: prefs.getString(Settings.PREF_MORE_POPUP_KEYS, Defaults.PREF_MORE_POPUP_KEYS)!!
Row {
TextButton(onClick = { showMorePopupsDialog = true }, Modifier.weight(1f))
{ Text(stringResource(morePopupKeysResId(value))) }
DefaultButton(explicitValue == null) {
setCurrentSubtype(currentSubtype.without(ExtraValue.MORE_POPUPS))
} }
} }
} }
} Row {
if (hasLocalizedNumberRow(currentSubtype.locale, ctx)) { TextButton(onClick = { showKeyOrderDialog = true }, Modifier.weight(1f))
Row(verticalAlignment = Alignment.CenterVertically) { { Text(stringResource(R.string.popup_order)) }
val checked = currentSubtype.getExtraValueOf(ExtraValue.LOCALIZED_NUMBER_ROW)?.toBoolean() DefaultButton(currentSubtype.getExtraValueOf(ExtraValue.POPUP_ORDER) == null) {
Text(stringResource(R.string.localized_number_row), Modifier.weight(1f)) setCurrentSubtype(currentSubtype.without(ExtraValue.POPUP_ORDER))
Switch(
checked = checked ?: prefs.getBoolean(Settings.PREF_LOCALIZED_NUMBER_ROW, Defaults.PREF_LOCALIZED_NUMBER_ROW),
onCheckedChange = {
setCurrentSubtype(currentSubtype.with(ExtraValue.LOCALIZED_NUMBER_ROW, it.toString()))
}
)
DefaultButton(checked == null) {
setCurrentSubtype(currentSubtype.without(ExtraValue.LOCALIZED_NUMBER_ROW))
} }
} }
} Row {
HorizontalDivider() TextButton(onClick = { showHintOrderDialog = true }, Modifier.weight(1f))
Text(stringResource(R.string.settings_screen_secondary_layouts), style = MaterialTheme.typography.titleMedium) { Text(stringResource(R.string.hint_source)) }
LayoutType.entries.forEach { type -> DefaultButton(currentSubtype.getExtraValueOf(ExtraValue.HINT_ORDER) == null) {
if (type == LayoutType.MAIN) return@forEach setCurrentSubtype(currentSubtype.without(ExtraValue.HINT_ORDER))
WithSmallTitle(stringResource(type.displayNameId)) { }
val explicitLayout = currentSubtype.layoutName(type) }
val layout = explicitLayout ?: Settings.readDefaultLayoutName(type, prefs) if (currentSubtype.locale.script() == ScriptUtils.SCRIPT_LATIN) {
val defaultLayouts = LayoutUtils.getAvailableLayouts(type, ctx) WithSmallTitle(stringResource(R.string.show_popup_keys_title)) {
val customLayouts = LayoutUtilsCustom.getLayoutFiles(type, ctx).map { it.name } val explicitValue = currentSubtype.getExtraValueOf(ExtraValue.MORE_POPUPS)
DropDownField( val value = explicitValue ?: prefs.getString(
items = defaultLayouts + customLayouts, Settings.PREF_MORE_POPUP_KEYS,
selectedItem = layout, Defaults.PREF_MORE_POPUP_KEYS
onSelected = { )!!
setCurrentSubtype(currentSubtype.withLayout(type, it)) Row {
}, TextButton(onClick = { showMorePopupsDialog = true }, Modifier.weight(1f))
extraButton = { DefaultButton(explicitLayout == null) { { Text(stringResource(morePopupKeysResId(value))) }
setCurrentSubtype(currentSubtype.withoutLayout(type)) DefaultButton(explicitValue == null) {
} }, setCurrentSubtype(currentSubtype.without(ExtraValue.MORE_POPUPS))
) { }
val displayName = if (LayoutUtilsCustom.isCustomLayout(it)) LayoutUtilsCustom.getDisplayName(it) }
else it.getStringResourceOrName("layout_", ctx) }
var showLayoutEditDialog by remember { mutableStateOf(false) } }
Row( if (hasLocalizedNumberRow(currentSubtype.locale, ctx)) {
horizontalArrangement = Arrangement.SpaceBetween, Row(verticalAlignment = Alignment.CenterVertically) {
verticalAlignment = Alignment.CenterVertically, val checked = currentSubtype.getExtraValueOf(ExtraValue.LOCALIZED_NUMBER_ROW)?.toBoolean()
modifier = Modifier.fillMaxWidth() Text(stringResource(R.string.localized_number_row), Modifier.weight(1f))
Switch(
checked = checked ?: prefs.getBoolean(
Settings.PREF_LOCALIZED_NUMBER_ROW,
Defaults.PREF_LOCALIZED_NUMBER_ROW
),
onCheckedChange = {
setCurrentSubtype(currentSubtype.with(ExtraValue.LOCALIZED_NUMBER_ROW, it.toString()))
}
)
DefaultButton(checked == null) {
setCurrentSubtype(currentSubtype.without(ExtraValue.LOCALIZED_NUMBER_ROW))
}
}
}
HorizontalDivider()
Text(
stringResource(R.string.settings_screen_secondary_layouts),
style = MaterialTheme.typography.titleMedium
)
LayoutType.entries.forEach { type ->
if (type == LayoutType.MAIN) return@forEach
WithSmallTitle(stringResource(type.displayNameId)) {
val explicitLayout = currentSubtype.layoutName(type)
val layout = explicitLayout ?: Settings.readDefaultLayoutName(type, prefs)
val defaultLayouts = LayoutUtils.getAvailableLayouts(type, ctx)
val customLayouts = LayoutUtilsCustom.getLayoutFiles(type, ctx).map { it.name }
DropDownField(
items = defaultLayouts + customLayouts,
selectedItem = layout,
onSelected = {
setCurrentSubtype(currentSubtype.withLayout(type, it))
},
extraButton = {
DefaultButton(explicitLayout == null) {
setCurrentSubtype(currentSubtype.withoutLayout(type))
}
},
) { ) {
Text(displayName) val displayName =
if (LayoutUtilsCustom.isCustomLayout(it)) if (LayoutUtilsCustom.isCustomLayout(it)) LayoutUtilsCustom.getDisplayName(it)
IconButton({ showLayoutEditDialog = true }) { Icon(painterResource(R.drawable.ic_edit), stringResource(R.string.edit_layout)) } else it.getStringResourceOrName("layout_", ctx)
var showLayoutEditDialog by remember { mutableStateOf(false) }
Row(
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.fillMaxWidth()
) {
Text(displayName)
if (LayoutUtilsCustom.isCustomLayout(it))
IconButton({
showLayoutEditDialog = true
}) {
Icon(
painterResource(R.drawable.ic_edit),
stringResource(R.string.edit_layout)
)
}
}
if (showLayoutEditDialog)
LayoutEditDialog(
onDismissRequest = { showLayoutEditDialog = false },
layoutType = type,
initialLayoutName = it,
isNameValid = null
)
} }
if (showLayoutEditDialog)
LayoutEditDialog(
onDismissRequest = { showLayoutEditDialog = false },
layoutType = type,
initialLayoutName = it,
isNameValid = null
)
} }
} }
} }
} }
} if (showSecondaryLocaleDialog)
if (showSecondaryLocaleDialog) MultiListPickerDialog(
MultiListPickerDialog( onDismissRequest = { showSecondaryLocaleDialog = false },
onDismissRequest = { showSecondaryLocaleDialog = false }, onConfirmed = { locales ->
onConfirmed = { locales -> val newValue = locales.joinToString(Separators.KV) { it.toLanguageTag() }
val newValue = locales.joinToString(Separators.KV) { it.toLanguageTag() } setCurrentSubtype(
setCurrentSubtype( if (newValue.isEmpty()) currentSubtype.without(ExtraValue.SECONDARY_LOCALES)
if (newValue.isEmpty()) currentSubtype.without(ExtraValue.SECONDARY_LOCALES) else currentSubtype.with(ExtraValue.SECONDARY_LOCALES, newValue)
else currentSubtype.with(ExtraValue.SECONDARY_LOCALES, newValue) )
) },
}, title = { Text(stringResource(R.string.locales_with_dict)) },
title = { Text(stringResource(R.string.locales_with_dict)) }, items = availableLocalesForScript,
items = availableLocalesForScript, initialSelection = currentSubtype.getExtraValueOf(ExtraValue.SECONDARY_LOCALES)
initialSelection = currentSubtype.getExtraValueOf(ExtraValue.SECONDARY_LOCALES) ?.split(Separators.KV)?.map { it.constructLocale() }.orEmpty(),
?.split(Separators.KV)?.map { it.constructLocale() }.orEmpty(), getItemName = { it.localizedDisplayName(ctx) }
getItemName = { it.localizedDisplayName(ctx) } )
) if (showKeyOrderDialog) {
if (showKeyOrderDialog) { val setting = currentSubtype.getExtraValueOf(ExtraValue.POPUP_ORDER)
val setting = currentSubtype.getExtraValueOf(ExtraValue.POPUP_ORDER) PopupOrderDialog(
PopupOrderDialog( onDismissRequest = { showKeyOrderDialog = false },
onDismissRequest = { showKeyOrderDialog = false }, initialValue = setting ?: prefs.getString(
initialValue = setting ?: prefs.getString(Settings.PREF_POPUP_KEYS_ORDER, Defaults.PREF_POPUP_KEYS_ORDER)!!, Settings.PREF_POPUP_KEYS_ORDER,
title = stringResource(R.string.popup_order), Defaults.PREF_POPUP_KEYS_ORDER
showDefault = setting != null, )!!,
onConfirmed = { title = stringResource(R.string.popup_order),
setCurrentSubtype( showDefault = setting != null,
if (it == null) currentSubtype.without(ExtraValue.POPUP_ORDER) onConfirmed = {
else currentSubtype.with(ExtraValue.POPUP_ORDER, it) setCurrentSubtype(
) if (it == null) currentSubtype.without(ExtraValue.POPUP_ORDER)
} else currentSubtype.with(ExtraValue.POPUP_ORDER, it)
) )
} }
if (showHintOrderDialog) { )
val setting = currentSubtype.getExtraValueOf(ExtraValue.HINT_ORDER) }
PopupOrderDialog( if (showHintOrderDialog) {
onDismissRequest = { showHintOrderDialog = false }, val setting = currentSubtype.getExtraValueOf(ExtraValue.HINT_ORDER)
initialValue = setting ?: prefs.getString(Settings.PREF_POPUP_KEYS_LABELS_ORDER, Defaults.PREF_POPUP_KEYS_LABELS_ORDER)!!, PopupOrderDialog(
title = stringResource(R.string.hint_source), onDismissRequest = { showHintOrderDialog = false },
showDefault = setting != null, initialValue = setting ?: prefs.getString(
onConfirmed = { Settings.PREF_POPUP_KEYS_LABELS_ORDER,
setCurrentSubtype( Defaults.PREF_POPUP_KEYS_LABELS_ORDER
if (it == null) currentSubtype.without(ExtraValue.HINT_ORDER) )!!,
else currentSubtype.with(ExtraValue.HINT_ORDER, it) title = stringResource(R.string.hint_source),
) showDefault = setting != null,
} onConfirmed = {
) setCurrentSubtype(
} if (it == null) currentSubtype.without(ExtraValue.HINT_ORDER)
if (showMorePopupsDialog) { else currentSubtype.with(ExtraValue.HINT_ORDER, it)
val items = listOf(POPUP_KEYS_NORMAL, POPUP_KEYS_MAIN, POPUP_KEYS_MORE, POPUP_KEYS_ALL) )
val explicitValue = currentSubtype.getExtraValueOf(ExtraValue.MORE_POPUPS) }
val value = explicitValue ?: prefs.getString(Settings.PREF_MORE_POPUP_KEYS, Defaults.PREF_MORE_POPUP_KEYS) )
ListPickerDialog( }
onDismissRequest = { showMorePopupsDialog = false }, if (showMorePopupsDialog) {
items = items, val items = listOf(POPUP_KEYS_NORMAL, POPUP_KEYS_MAIN, POPUP_KEYS_MORE, POPUP_KEYS_ALL)
getItemName = { stringResource(morePopupKeysResId(it)) }, val explicitValue = currentSubtype.getExtraValueOf(ExtraValue.MORE_POPUPS)
selectedItem = value, val value = explicitValue ?: prefs.getString(Settings.PREF_MORE_POPUP_KEYS, Defaults.PREF_MORE_POPUP_KEYS)
onItemSelected = { setCurrentSubtype(currentSubtype.with(ExtraValue.MORE_POPUPS, it)) } ListPickerDialog(
) onDismissRequest = { showMorePopupsDialog = false },
items = items,
getItemName = { stringResource(morePopupKeysResId(it)) },
selectedItem = value,
onItemSelected = { setCurrentSubtype(currentSubtype.with(ExtraValue.MORE_POPUPS, it)) }
)
}
} }
} }