From bc5b9b4efc66ff6bafafe466cc497f9a395fc07e Mon Sep 17 00:00:00 2001 From: Helium314 Date: Sun, 2 Feb 2025 17:07:53 +0100 Subject: [PATCH] use simple list picker --- .../helium314/keyboard/settings/Preference.kt | 10 +- .../settings/dialogs/ListPickerDialog.kt | 2 +- .../dialogs/SimpleListPickerDialog.kt | 138 ++++++++++++++++++ .../settings/screens/TextCorrectionScreen.kt | 7 +- 4 files changed, 147 insertions(+), 10 deletions(-) create mode 100644 app/src/main/java/helium314/keyboard/settings/dialogs/SimpleListPickerDialog.kt diff --git a/app/src/main/java/helium314/keyboard/settings/Preference.kt b/app/src/main/java/helium314/keyboard/settings/Preference.kt index 55f98b8bd..f4fb8eb16 100644 --- a/app/src/main/java/helium314/keyboard/settings/Preference.kt +++ b/app/src/main/java/helium314/keyboard/settings/Preference.kt @@ -40,7 +40,7 @@ import helium314.keyboard.latin.R import helium314.keyboard.latin.utils.Log import helium314.keyboard.latin.utils.getActivity import helium314.keyboard.latin.utils.prefs -import helium314.keyboard.settings.dialogs.ListPickerDialog +import helium314.keyboard.settings.dialogs.SimpleListPickerDialog import helium314.keyboard.settings.dialogs.SliderDialog // taken from StreetComplete (and a bit SCEE) @@ -82,14 +82,14 @@ fun Preference( modifier = modifier .fillMaxWidth() .clickable { onClick() } - .heightIn(min = 40.dp) + .heightIn(min = 44.dp) .padding(12.dp), horizontalArrangement = Arrangement.spacedBy(12.dp), verticalAlignment = Alignment.CenterVertically ) { if (icon != null) Icon(painterResource(icon), name, modifier = Modifier.size(36.dp)) - Column(modifier = Modifier.weight(2 / 3f)) { + Column(modifier = Modifier.weight(1f)) { Text(text = name) if (description != null) { CompositionLocalProvider( @@ -117,7 +117,6 @@ fun Preference( alignment = Alignment.End ), verticalAlignment = Alignment.CenterVertically, - modifier = Modifier.weight(1 / 3f) ) { value() } } } @@ -233,7 +232,6 @@ fun ListPreference( default: T, ) { var showDialog by remember { mutableStateOf(false) } - // todo: get rid of the arrays from old settings val prefs = LocalContext.current.prefs() val selected = items.firstOrNull { it.second == getPrefOfType(prefs, def.key, default) } Preference( @@ -242,7 +240,7 @@ fun ListPreference( onClick = { showDialog = true } ) if (showDialog) { - ListPickerDialog( + SimpleListPickerDialog( onDismissRequest = { showDialog = false }, items = items, onItemSelected = { diff --git a/app/src/main/java/helium314/keyboard/settings/dialogs/ListPickerDialog.kt b/app/src/main/java/helium314/keyboard/settings/dialogs/ListPickerDialog.kt index 5d908cbb0..f5687d73f 100644 --- a/app/src/main/java/helium314/keyboard/settings/dialogs/ListPickerDialog.kt +++ b/app/src/main/java/helium314/keyboard/settings/dialogs/ListPickerDialog.kt @@ -33,7 +33,7 @@ import androidx.compose.ui.window.DialogProperties // taken from StreetComplete @Composable -fun ListPickerDialog( +fun ListPickerDialog( onDismissRequest: () -> Unit, items: List, onItemSelected: (T) -> Unit, diff --git a/app/src/main/java/helium314/keyboard/settings/dialogs/SimpleListPickerDialog.kt b/app/src/main/java/helium314/keyboard/settings/dialogs/SimpleListPickerDialog.kt new file mode 100644 index 000000000..a606a6e5c --- /dev/null +++ b/app/src/main/java/helium314/keyboard/settings/dialogs/SimpleListPickerDialog.kt @@ -0,0 +1,138 @@ +package helium314.keyboard.settings.dialogs + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.lazy.rememberLazyListState +import androidx.compose.material3.HorizontalDivider +import androidx.compose.material3.LocalTextStyle +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.RadioButton +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton +import androidx.compose.material3.contentColorFor +import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +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.Color +import androidx.compose.ui.graphics.Shape +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.window.Dialog +import androidx.compose.ui.window.DialogProperties + +// taken from StreetComplete +/** Similar to ListPickerDialog, but tapping on one item immediately closes the dialog + * (no OK button, no cancel button) + * + * This dialog doesn't have the caveat of the ListPickerDialog in that it takes as much width + * as possible */ +@Composable +fun SimpleListPickerDialog( + onDismissRequest: () -> Unit, + items: List, + onItemSelected: (T) -> Unit, + title: (@Composable () -> Unit)? = null, + selectedItem: T? = null, + getItemName: (@Composable (T) -> String) = { it.toString() }, + shape: Shape = MaterialTheme.shapes.medium, + backgroundColor: Color = MaterialTheme.colorScheme.surface, + contentColor: Color = contentColorFor(backgroundColor), + properties: DialogProperties = DialogProperties() +) { + val selected by remember { mutableStateOf(selectedItem) } + val state = rememberLazyListState() + + fun select(item: T) { + onDismissRequest() + onItemSelected(item) + } + + LaunchedEffect(selectedItem) { + val index = items.indexOf(selectedItem) + if (index != -1) state.scrollToItem(index, -state.layoutInfo.viewportSize.height / 3) + } + + Dialog( + onDismissRequest = onDismissRequest, + properties = properties + ) { + Surface( + shape = shape, + color = backgroundColor, + contentColor = contentColor + ) { + Column(Modifier.padding(vertical = 24.dp)) { + if (title != null) { + CompositionLocalProvider( + LocalTextStyle provides MaterialTheme.typography.titleLarge + ) { + Column(Modifier.padding(start = 24.dp, bottom = 16.dp, end = 24.dp)) { + title() + } + } + } + if (state.canScrollBackward) HorizontalDivider() + CompositionLocalProvider( + LocalTextStyle provides MaterialTheme.typography.bodyLarge + ) { + LazyColumn(state = state) { + items(items) { item -> + Row( + horizontalArrangement = Arrangement.spacedBy(16.dp), + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier + .clickable { select(item) } + .padding(horizontal = 24.dp) + ) { + Text( + text = getItemName(item), + style = MaterialTheme.typography.bodyLarge, + modifier = Modifier.weight(1f), + ) + RadioButton( + selected = selected == item, + onClick = { select(item) } + ) + } + } + } + } + if (state.canScrollForward) HorizontalDivider() + // todo: button not visible when there are many entries + Row(Modifier.padding(end = 24.dp)) { + Spacer(Modifier.weight(1f)) + TextButton( + onClick = onDismissRequest, + ) { Text(stringResource(android.R.string.cancel)) } + } + } + } + } +} + +@Preview +@Composable +private fun PreviewSimpleListPickerDialog() { + val items = remember { (0..<5).toList() } + SimpleListPickerDialog( + onDismissRequest = {}, + items = items, + onItemSelected = {}, + title = { Text("Select something") }, + selectedItem = 2, + getItemName = { "Item $it" }, + ) +} diff --git a/app/src/main/java/helium314/keyboard/settings/screens/TextCorrectionScreen.kt b/app/src/main/java/helium314/keyboard/settings/screens/TextCorrectionScreen.kt index 253424efe..545a580dd 100644 --- a/app/src/main/java/helium314/keyboard/settings/screens/TextCorrectionScreen.kt +++ b/app/src/main/java/helium314/keyboard/settings/screens/TextCorrectionScreen.kt @@ -131,7 +131,6 @@ fun createCorrectionPrefs(context: Context) = listOf( Settings.PREF_AUTO_CORRECTION_CONFIDENCE, R.string.auto_correction_confidence, ) { def -> - // todo: arrays are arranged in a rather absurd way... this should be improved val items = listOf( stringResource(R.string.auto_correction_threshold_mode_modest) to "0", stringResource(R.string.auto_correction_threshold_mode_aggressive) to "1", @@ -225,14 +224,16 @@ fun createCorrectionPrefs(context: Context) = listOf( Settings.PREF_USE_CONTACTS, R.string.use_contacts_dict, R.string.use_contacts_dict_summary - ) { + ) { def -> val activity = LocalContext.current.getActivity() ?: return@PrefDef var granted by remember { mutableStateOf(PermissionsUtil.checkAllPermissionsGranted(activity, Manifest.permission.READ_CONTACTS)) } val launcher = rememberLauncherForActivityResult(ActivityResultContracts.RequestPermission()) { granted = it + if (granted) + activity.prefs().edit().putBoolean(def.key, true).apply() } SwitchPreference( - it, + def, false, allowCheckedChange = { if (it && !granted) {