add dialog with default button

This commit is contained in:
Helium314 2025-02-02 15:04:40 +01:00
parent e2ebd32f25
commit 31b2a36bcc
10 changed files with 183 additions and 82 deletions

View file

@ -14,9 +14,6 @@ import helium314.keyboard.latin.utils.prefs
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
// todo (roughly in order) // todo (roughly in order)
// default buttons for toolbar key(s) customizer, icon customizer, and toolbar reorder dialog
// make a dialog wrapper that has a default button?
// yes, definitely need a 3 button dialog...
// make all prefs actually work // make all prefs actually work
// try moving the recomposition of pref change somewhere else, so it's not duplicated everywhere // try moving the recomposition of pref change somewhere else, so it's not duplicated everywhere
// make the pref lists more compact (compare with old settings) // make the pref lists more compact (compare with old settings)

View file

@ -56,11 +56,16 @@ fun CustomizeIconsDialog(
else iconName to name else iconName to name
}.sortedBy { it.second } }.sortedBy { it.second }
var showIconDialog: Pair<String, String>? by remember { mutableStateOf(null) } var showIconDialog: Pair<String, String>? by remember { mutableStateOf(null) }
var showDeletePrefConfirmDialog by remember { mutableStateOf(false) }
val prefs = ctx.prefs() val prefs = ctx.prefs()
AlertDialog( AlertDialog(
onDismissRequest = onDismissRequest, onDismissRequest = onDismissRequest,
confirmButton = { }, // no confirm button confirmButton = { TextButton(onClick = onDismissRequest) { Text(stringResource(R.string.dialog_close)) } },
dismissButton = { TextButton(onClick = onDismissRequest) { Text(stringResource(R.string.dialog_close)) } }, dismissButton = {
if (prefs.contains(prefKey))
TextButton(onClick = { showDeletePrefConfirmDialog = true })
{ Text(stringResource(R.string.button_default)) }
},
title = { Text(stringResource(R.string.customize_icons)) }, title = { Text(stringResource(R.string.customize_icons)) },
text = { text = {
LazyColumn(state = state) { LazyColumn(state = state) {
@ -82,24 +87,31 @@ fun CustomizeIconsDialog(
val iconsForName = allIcons[iconName].orEmpty() val iconsForName = allIcons[iconName].orEmpty()
val iconsSet = mutableSetOf<Int>() val iconsSet = mutableSetOf<Int>()
iconsSet.addAll(iconsForName) iconsSet.addAll(iconsForName)
KeyboardIconsSet.getAllIcons(ctx).forEach { iconsSet.addAll(it.value) } // is this called again on UI interaction? KeyboardIconsSet.getAllIcons(ctx).forEach { iconsSet.addAll(it.value) } // todo: is this called again on UI interaction?
val icons = iconsSet.toList() val icons = iconsSet.toList()
var selectedIcon by remember { mutableStateOf(KeyboardIconsSet.instance.iconIds[iconName]) } var selectedIcon by remember { mutableStateOf(KeyboardIconsSet.instance.iconIds[iconName]) }
AlertDialog( ThreeButtonAlertDialog(
onDismissRequest = onDismissRequest, onDismissRequest = onDismissRequest,
confirmButton = { TextButton( onConfirmed = {
onClick = { runCatching {
onDismissRequest() val newIcons = customIconNames(prefs).toMutableMap()
runCatching { newIcons[iconName] = selectedIcon?.let { ctx.resources.getResourceEntryName(it) } ?: return@runCatching
val newIcons = customIconNames(prefs).toMutableMap() prefs.edit().putString(prefKey, Json.encodeToString(newIcons)).apply()
newIcons[iconName] = selectedIcon?.let { ctx.resources.getResourceEntryName(it) } ?: return@runCatching KeyboardIconsSet.instance.loadIcons(ctx)
prefs.edit().putString(prefKey, Json.encodeToString(newIcons)).apply()
KeyboardIconsSet.instance.loadIcons(ctx)
}
// todo: show outer dialog again and reload icons?
} }
) { Text(stringResource(android.R.string.ok)) } }, // todo: show outer dialog again and reload icons?
dismissButton = { TextButton(onClick = onDismissRequest) { Text(stringResource(android.R.string.cancel)) } }, },
neutralButtonText = if (customIconNames(prefs).contains(iconName)) stringResource(R.string.button_default) else null,
onNeutral = {
runCatching {
val icons2 = customIconNames(prefs).toMutableMap()
icons2.remove(iconName)
if (icons2.isEmpty()) prefs.edit().remove(prefKey).apply()
else prefs.edit().putString(prefKey, Json.encodeToString(icons2)).apply()
KeyboardIconsSet.instance.loadIcons(ctx)
}
// todo: show outer dialog again and reload icons?
},
title = { Text(showIconDialog!!.second) }, title = { Text(showIconDialog!!.second) },
text = { text = {
LazyVerticalGrid( LazyVerticalGrid(
@ -129,6 +141,16 @@ fun CustomizeIconsDialog(
}, },
) )
} }
if (showDeletePrefConfirmDialog)
ConfirmationDialog(
onDismissRequest = { showDeletePrefConfirmDialog = false },
onConfirmed = {
showDeletePrefConfirmDialog = false
onDismissRequest()
prefs.edit().remove(prefKey).apply()
},
text = { Text(stringResource(R.string.customize_icons_reset_message)) }
)
} }
@Preview @Preview

View file

@ -28,8 +28,6 @@ fun LayoutEditDialog(
val initialText = startContent ?: file.readText() val initialText = startContent ?: file.readText()
var showDeleteConfirmation by remember { mutableStateOf(false) } var showDeleteConfirmation by remember { mutableStateOf(false) }
// todo: try make it really full width, at least if we have a json file // todo: try make it really full width, at least if we have a json file
// todo: ok button should be "save"
// todo: if displayName not null, there is an existing file
TextInputDialog( TextInputDialog(
onDismissRequest = onDismissRequest, onDismissRequest = onDismissRequest,
onConfirmed = { onConfirmed = {
@ -38,13 +36,20 @@ fun LayoutEditDialog(
onCustomLayoutFileListChanged() onCustomLayoutFileListChanged()
keyboardNeedsReload = true keyboardNeedsReload = true
}, },
confirmButtonText = stringResource(R.string.save),
neutralButtonText = if (displayName != null && file.exists()) stringResource(R.string.delete) else null,
onNeutral = {
if (!file.exists()) return@TextInputDialog
file.delete()
onCustomLayoutFileListChanged()
keyboardNeedsReload = true
},
initialText = initialText, initialText = initialText,
singleLine = false, singleLine = false,
title = { Text(displayName ?: getLayoutDisplayName(layoutName)) }, title = { Text(displayName ?: getLayoutDisplayName(layoutName)) },
checkTextValid = { checkTextValid = {
checkLayout(it, ctx) // todo: toast with reason why it doesn't work -> should re-do getting the reason checkLayout(it, ctx) // todo: toast with reason why it doesn't work -> should re-do getting the reason
}, },
// todo: delete button if displayName not null and file exists
) )
if (showDeleteConfirmation) if (showDeleteConfirmation)
ConfirmationDialog( ConfirmationDialog(

View file

@ -43,8 +43,8 @@ fun <T: Any> ReorderDialog(
displayItem: @Composable (T) -> Unit, displayItem: @Composable (T) -> Unit,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
title: @Composable (() -> Unit)? = null, title: @Composable (() -> Unit)? = null,
confirmButtonText: String = stringResource(android.R.string.ok), onNeutral: () -> Unit = { },
cancelButtonText: String = stringResource(android.R.string.cancel), neutralButtonText: String? = null,
shape: Shape = MaterialTheme.shapes.medium, shape: Shape = MaterialTheme.shapes.medium,
backgroundColor: Color = MaterialTheme.colorScheme.surface, backgroundColor: Color = MaterialTheme.colorScheme.surface,
contentColor: Color = contentColorFor(backgroundColor), contentColor: Color = contentColorFor(backgroundColor),
@ -58,13 +58,12 @@ fun <T: Any> ReorderDialog(
add(to.index, removeAt(from.index)) add(to.index, removeAt(from.index))
} }
} }
AlertDialog( ThreeButtonAlertDialog(
onDismissRequest = onDismissRequest, onDismissRequest = onDismissRequest,
confirmButton = { onConfirmed = { onConfirmed(reorderableItems) },
TextButton(onClick = { onConfirmed(reorderableItems); onDismissRequest() }) { Text(confirmButtonText) } onNeutral = onNeutral,
}, neutralButtonText = neutralButtonText,
modifier = modifier, modifier = modifier,
dismissButton = { TextButton(onClick = onDismissRequest) { Text(cancelButtonText) } },
title = title, title = title,
text = { text = {
LazyColumn( LazyColumn(
@ -93,8 +92,8 @@ fun <T: Any> ReorderDialog(
} }
}, },
shape = shape, shape = shape,
containerColor = backgroundColor, backgroundColor = backgroundColor,
textContentColor = contentColor, contentColor = contentColor,
properties = properties, properties = properties,
) )
} }

View file

@ -32,7 +32,7 @@ fun SliderDialog(
range: ClosedFloatingPointRange<Float>, range: ClosedFloatingPointRange<Float>,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
showDefault: Boolean = false, showDefault: Boolean = false,
onDefault: () -> Unit? = { }, onDefault: () -> Unit = { },
onValueChanged: (Float) -> Unit = { }, onValueChanged: (Float) -> Unit = { },
title: (@Composable () -> Unit)? = null, title: (@Composable () -> Unit)? = null,
intermediateSteps: Int? = null, intermediateSteps: Int? = null,
@ -44,21 +44,11 @@ fun SliderDialog(
) { ) {
var sliderPosition by remember { mutableFloatStateOf(initialValue) } var sliderPosition by remember { mutableFloatStateOf(initialValue) }
AlertDialog( ThreeButtonAlertDialog(
onDismissRequest = onDismissRequest, onDismissRequest = onDismissRequest,
confirmButton = { // mis-use the confirm button and put everything in there neutralButtonText = if (showDefault) stringResource(R.string.button_default) else null,
Row { onNeutral = onDefault,
if (showDefault) onConfirmed = { onDone(sliderPosition) },
TextButton(
onClick = { onDismissRequest(); onDefault() }
) { Text(stringResource(R.string.button_default)) }
Spacer(modifier.weight(1f))
TextButton(onClick = onDismissRequest) { Text(stringResource(android.R.string.cancel)) }
TextButton(
onClick = { onDismissRequest(); onDone(sliderPosition) },
) { Text(stringResource(android.R.string.ok)) }
}
},
modifier = modifier, modifier = modifier,
title = title, title = title,
text = { text = {
@ -86,8 +76,8 @@ fun SliderDialog(
} }
}, },
shape = shape, shape = shape,
containerColor = backgroundColor, backgroundColor = backgroundColor,
textContentColor = contentColor, contentColor = contentColor,
properties = properties, properties = properties,
) )
} }

View file

@ -2,11 +2,9 @@ package helium314.keyboard.settings.dialogs
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.contentColorFor import androidx.compose.material3.contentColorFor
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
@ -26,7 +24,7 @@ import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.window.DialogProperties import androidx.compose.ui.window.DialogProperties
// taken from StreetComplete / SCEE // mostly taken from StreetComplete / SCEE
/** Dialog with which to input text. OK button is only clickable if [checkTextValid] returns true. */ /** Dialog with which to input text. OK button is only clickable if [checkTextValid] returns true. */
@Composable @Composable
fun TextInputDialog( fun TextInputDialog(
@ -34,6 +32,9 @@ fun TextInputDialog(
onConfirmed: (text: String) -> Unit, onConfirmed: (text: String) -> Unit,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
title: @Composable (() -> Unit)? = null, title: @Composable (() -> Unit)? = null,
onNeutral: () -> Unit = { },
neutralButtonText: String? = null,
confirmButtonText: String = stringResource(android.R.string.ok),
initialText: String = "", initialText: String = "",
textInputLabel: @Composable (() -> Unit)? = null, textInputLabel: @Composable (() -> Unit)? = null,
shape: Shape = MaterialTheme.shapes.medium, shape: Shape = MaterialTheme.shapes.medium,
@ -52,34 +53,30 @@ fun TextInputDialog(
LaunchedEffect(initialText) { focusRequester.requestFocus() } LaunchedEffect(initialText) { focusRequester.requestFocus() }
AlertDialog( ThreeButtonAlertDialog(
onDismissRequest = onDismissRequest, onDismissRequest = onDismissRequest,
confirmButton = { onConfirmed = { onConfirmed(value.text) },
TextButton( confirmButtonText = confirmButtonText,
enabled = value.text.isNotBlank() && checkTextValid(value.text), checkOk = { checkTextValid(value.text) },
onClick = { onDismissRequest(); onConfirmed(value.text) } neutralButtonText = neutralButtonText,
) { onNeutral = onNeutral,
Text(stringResource(android.R.string.ok))
}
},
dismissButton = {
TextButton(onClick = onDismissRequest) { Text(stringResource(android.R.string.cancel)) }
},
modifier = modifier, modifier = modifier,
title = title, title = title,
text = { text = {
OutlinedTextField( OutlinedTextField(
value = value, value = value,
onValueChange = { value = it }, onValueChange = { value = it },
modifier = Modifier.fillMaxWidth().focusRequester(focusRequester), modifier = Modifier
.fillMaxWidth()
.focusRequester(focusRequester),
label = textInputLabel, label = textInputLabel,
keyboardOptions = KeyboardOptions(keyboardType = keyboardType), keyboardOptions = KeyboardOptions(keyboardType = keyboardType),
singleLine = singleLine singleLine = singleLine
) )
}, },
shape = shape, shape = shape,
containerColor = backgroundColor, backgroundColor = backgroundColor,
textContentColor = contentColor, contentColor = contentColor,
properties = properties, properties = properties,
) )
} }

View file

@ -0,0 +1,58 @@
package helium314.keyboard.settings.dialogs
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.contentColorFor
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.window.DialogProperties
@Composable
fun ThreeButtonAlertDialog(
onDismissRequest: () -> Unit,
onConfirmed: () -> Unit,
modifier: Modifier = Modifier,
title: @Composable (() -> Unit)? = null,
text: @Composable (() -> Unit)? = null,
onNeutral: () -> Unit = { },
checkOk: () -> Boolean = { true },
confirmButtonText: String = stringResource(android.R.string.ok),
cancelButtonText: String = stringResource(android.R.string.cancel),
neutralButtonText: String? = null,
shape: Shape = MaterialTheme.shapes.medium,
backgroundColor: Color = MaterialTheme.colorScheme.surface,
contentColor: Color = contentColorFor(backgroundColor),
properties: DialogProperties = DialogProperties(),
) {
AlertDialog(
onDismissRequest = onDismissRequest,
confirmButton = { // mis-use the confirm button and put everything in there
Row {
if (neutralButtonText != null)
TextButton(
onClick = { onDismissRequest(); onNeutral() }
) { Text(neutralButtonText) }
Spacer(modifier.weight(1f))
TextButton(onClick = onDismissRequest) { Text(cancelButtonText) }
TextButton(
enabled = checkOk(),
onClick = { onDismissRequest(); onConfirmed() },
) { Text(confirmButtonText) }
}
},
modifier = modifier,
title = title,
text = text,
shape = shape,
containerColor = backgroundColor,
textContentColor = contentColor,
properties = properties,
)
}

View file

@ -25,6 +25,7 @@ import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.window.DialogProperties import androidx.compose.ui.window.DialogProperties
import androidx.core.content.edit
import helium314.keyboard.keyboard.internal.KeyboardIconsSet import helium314.keyboard.keyboard.internal.KeyboardIconsSet
import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyCode.checkAndConvertCode import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyCode.checkAndConvertCode
import helium314.keyboard.latin.R import helium314.keyboard.latin.R
@ -39,21 +40,28 @@ import helium314.keyboard.latin.utils.readCustomLongpressCodes
import helium314.keyboard.latin.utils.writeCustomKeyCodes import helium314.keyboard.latin.utils.writeCustomKeyCodes
import helium314.keyboard.latin.utils.writeCustomLongpressCodes import helium314.keyboard.latin.utils.writeCustomLongpressCodes
import helium314.keyboard.settings.screens.GetIcon import helium314.keyboard.settings.screens.GetIcon
import kotlinx.serialization.json.Json
// todo: // todo (later): reading and writing prefs should be done in the preference, or at least with the provided (single!) pref key
// reading and writing prefs should be done in the preference, or at least with the provided (single!) key
@Composable @Composable
fun ToolbarKeysCustomizer( fun ToolbarKeysCustomizer(
onDismissRequest: () -> Unit onDismissRequest: () -> Unit
) { ) {
val ctx = LocalContext.current val ctx = LocalContext.current
val prefs = ctx.prefs()
var showKeyCustomizer: ToolbarKey? by remember { mutableStateOf(null) } var showKeyCustomizer: ToolbarKey? by remember { mutableStateOf(null) }
var showDeletePrefConfirmDialog by remember { mutableStateOf(false) }
AlertDialog( AlertDialog(
onDismissRequest = onDismissRequest, onDismissRequest = onDismissRequest,
confirmButton = { confirmButton = {
TextButton(onClick = onDismissRequest) { Text(stringResource(R.string.dialog_close)) } TextButton(onClick = onDismissRequest) { Text(stringResource(R.string.dialog_close)) }
}, },
dismissButton = { }, dismissButton = {
if (readCustomKeyCodes(prefs).isNotEmpty() || readCustomLongpressCodes(prefs).isNotEmpty())
TextButton(
onClick = { showDeletePrefConfirmDialog = true }
) { Text(stringResource(R.string.button_default)) }
},
title = { Text(stringResource(R.string.customize_toolbar_key_codes)) }, title = { Text(stringResource(R.string.customize_toolbar_key_codes)) },
text = { text = {
LazyColumn { LazyColumn {
@ -78,8 +86,22 @@ fun ToolbarKeysCustomizer(
if (shownKey != null) if (shownKey != null)
ToolbarKeyCustomizer(shownKey) { showKeyCustomizer = null } ToolbarKeyCustomizer(shownKey) { showKeyCustomizer = null }
} }
if (showDeletePrefConfirmDialog)
ConfirmationDialog(
onDismissRequest = { showDeletePrefConfirmDialog = false },
onConfirmed = {
showDeletePrefConfirmDialog = false
onDismissRequest()
prefs.edit {
remove(Settings.PREF_TOOLBAR_CUSTOM_KEY_CODES)
remove(Settings.PREF_TOOLBAR_CUSTOM_LONGPRESS_CODES)
}
},
text = { Text(stringResource(R.string.customize_toolbar_key_code_reset_message)) }
)
} }
// todo: show updated ToolbarKeysCustomizer after ok / default? because default button
@Composable @Composable
private fun ToolbarKeyCustomizer( private fun ToolbarKeyCustomizer(
key: ToolbarKey, key: ToolbarKey,
@ -89,19 +111,24 @@ private fun ToolbarKeyCustomizer(
val prefs = ctx.prefs() val prefs = ctx.prefs()
var code by remember { mutableStateOf(TextFieldValue(getCodeForToolbarKey(key).toString())) } var code by remember { mutableStateOf(TextFieldValue(getCodeForToolbarKey(key).toString())) }
var longPressCode by remember { mutableStateOf(TextFieldValue(getCodeForToolbarKeyLongClick(key).toString())) } var longPressCode by remember { mutableStateOf(TextFieldValue(getCodeForToolbarKeyLongClick(key).toString())) }
AlertDialog( ThreeButtonAlertDialog(
onDismissRequest = onDismissRequest, onDismissRequest = onDismissRequest,
confirmButton = { onConfirmed = {
TextButton( writeCustomKeyCodes(prefs, readCustomKeyCodes(prefs) + (key.name to checkCode(code)))
onClick = { writeCustomLongpressCodes(prefs, readCustomLongpressCodes(prefs) + (key.name to checkCode(longPressCode)))
writeCustomKeyCodes(prefs, readCustomKeyCodes(prefs) + (key.name to checkCode(code))) },
writeCustomLongpressCodes(prefs, readCustomLongpressCodes(prefs) + (key.name to checkCode(longPressCode))) checkOk = { checkCode(code) != null && checkCode(longPressCode) != null },
onDismissRequest() neutralButtonText = if (readCustomKeyCodes(prefs).containsKey(key.name) || readCustomLongpressCodes(prefs).containsKey(key.name))
}, stringResource(R.string.button_default)
enabled = checkCode(code) != null && checkCode(longPressCode) != null else null,
) { Text(stringResource(android.R.string.ok)) } onNeutral = {
val keys = readCustomKeyCodes(prefs).toMutableMap()
keys.remove(key.name)
prefs.edit().putString(Settings.PREF_TOOLBAR_CUSTOM_KEY_CODES, Json.encodeToString(keys)).apply()
val longpressKeys = readCustomLongpressCodes(prefs).toMutableMap()
longpressKeys.remove(key.name)
prefs.edit().putString(Settings.PREF_TOOLBAR_CUSTOM_LONGPRESS_CODES, Json.encodeToString(longpressKeys)).apply()
}, },
dismissButton = { TextButton(onClick = onDismissRequest) { Text(stringResource(android.R.string.cancel)) } },
title = { Text(key.name.lowercase().getStringResourceOrName("", ctx)) }, title = { Text(key.name.lowercase().getStringResourceOrName("", ctx)) },
text = { text = {
Column { Column {
@ -126,8 +153,8 @@ private fun ToolbarKeyCustomizer(
} }
}, },
shape = MaterialTheme.shapes.medium, shape = MaterialTheme.shapes.medium,
containerColor = MaterialTheme.colorScheme.surface, backgroundColor = MaterialTheme.colorScheme.surface,
textContentColor = contentColorFor(MaterialTheme.colorScheme.surface), contentColor = contentColorFor(MaterialTheme.colorScheme.surface),
properties = DialogProperties(), properties = DialogProperties(),
) )
} }

View file

@ -131,6 +131,10 @@ fun createAppearancePrefs(context: Context) = listOf(
onClick = { showDialog = true } onClick = { showDialog = true }
) )
if (showDialog) { if (showDialog) {
if (keyboardNeedsReload) {
KeyboardSwitcher.getInstance().forceUpdateKeyboardTheme(LocalContext.current)
keyboardNeedsReload = false
}
CustomizeIconsDialog(def.key) { showDialog = false } CustomizeIconsDialog(def.key) { showDialog = false }
} }
}, },

View file

@ -165,6 +165,8 @@ fun ToolbarKeyReorderDialog(
keyboardNeedsReload = true keyboardNeedsReload = true
}, },
onDismissRequest = onDismiss, onDismissRequest = onDismiss,
onNeutral = { prefs.edit().remove(prefKey).apply() },
neutralButtonText = if (prefs.contains(prefKey)) stringResource(R.string.button_default) else null,
items = items, items = items,
title = { Text(title) }, title = { Text(title) },
displayItem = { item -> displayItem = { item ->