use simple list picker

This commit is contained in:
Helium314 2025-02-02 17:07:53 +01:00
parent 80172665c0
commit bc5b9b4efc
4 changed files with 147 additions and 10 deletions

View file

@ -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 <T: Any> 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 <T: Any> ListPreference(
onClick = { showDialog = true }
)
if (showDialog) {
ListPickerDialog(
SimpleListPickerDialog(
onDismissRequest = { showDialog = false },
items = items,
onItemSelected = {

View file

@ -33,7 +33,7 @@ import androidx.compose.ui.window.DialogProperties
// taken from StreetComplete
@Composable
fun <T> ListPickerDialog(
fun <T: Any> ListPickerDialog(
onDismissRequest: () -> Unit,
items: List<T>,
onItemSelected: (T) -> Unit,

View file

@ -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 <T> SimpleListPickerDialog(
onDismissRequest: () -> Unit,
items: List<T>,
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" },
)
}

View file

@ -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) {