diff --git a/app/src/main/java/helium314/keyboard/latin/utils/ToolbarUtils.kt b/app/src/main/java/helium314/keyboard/latin/utils/ToolbarUtils.kt index 6cb94ff79..ad647fa86 100644 --- a/app/src/main/java/helium314/keyboard/latin/utils/ToolbarUtils.kt +++ b/app/src/main/java/helium314/keyboard/latin/utils/ToolbarUtils.kt @@ -299,12 +299,12 @@ fun readCustomLongpressCodes(prefs: SharedPreferences) = prefs.getString(Setting it.substringBefore(",") to code } -private fun writeCustomKeyCodes(prefs: SharedPreferences, codes: Map) { +fun writeCustomKeyCodes(prefs: SharedPreferences, codes: Map) { val string = codes.mapNotNull { entry -> entry.value?.let { "${entry.key},$it" } }.joinToString(";") prefs.edit().putString(Settings.PREF_TOOLBAR_CUSTOM_KEY_CODES, string).apply() } -private fun writeCustomLongpressCodes(prefs: SharedPreferences, codes: Map) { +fun writeCustomLongpressCodes(prefs: SharedPreferences, codes: Map) { val string = codes.mapNotNull { entry -> entry.value?.let { "${entry.key},$it" } }.joinToString(";") prefs.edit().putString(Settings.PREF_TOOLBAR_CUSTOM_LONGPRESS_CODES, string).apply() } diff --git a/app/src/main/java/helium314/keyboard/settings/SettingsActivity.kt b/app/src/main/java/helium314/keyboard/settings/SettingsActivity.kt index 2618b2980..62e7c93b5 100644 --- a/app/src/main/java/helium314/keyboard/settings/SettingsActivity.kt +++ b/app/src/main/java/helium314/keyboard/settings/SettingsActivity.kt @@ -22,6 +22,8 @@ import kotlinx.coroutines.flow.MutableStateFlow // screens could have a lazy column of preferences and category separators, and the list has an if-setting-then-null for hiding // lazyColumn also has the key, this should be used! and must be unique // consider that stuff in composables can get called quite often on any changes -> use remember for things that are slow (maybe add test logging) +// dialogs should be rememberSaveable to survive display orientation change and stuff? +// default buttons for toolbar key(s) customizer and toolbar reorder dialog // later // one single place for default values (in composables and settings) @@ -41,12 +43,16 @@ import kotlinx.coroutines.flow.MutableStateFlow // -> now toolbar key always has the wrong state // color settings needs a color search // more convenient access to prefs +// merge PREF_TOOLBAR_CUSTOM_KEY_CODES and PREF_TOOLBAR_CUSTOM_LONGPRESS_CODES +// should be single pref containing both +// needs settings upgrade of course... // consider disabled settings & search // don't show -> users confused // show as disabled -> users confused // show (but change will not do anything because another setting needs to be enabled first) // -> users confused, but probably better than the 2 above // adjust layout a little, there is too much empty space and titles are too large (dialogs!) +// check dialogs have the same colors // maybe later // weird problem with app sometimes closing on back, but that's related to "old" settings (don't care if all are removed) diff --git a/app/src/main/java/helium314/keyboard/settings/dialogs/ToolbarKeysCustomizer.kt b/app/src/main/java/helium314/keyboard/settings/dialogs/ToolbarKeysCustomizer.kt new file mode 100644 index 000000000..b13f5ab6e --- /dev/null +++ b/app/src/main/java/helium314/keyboard/settings/dialogs/ToolbarKeysCustomizer.kt @@ -0,0 +1,152 @@ +package helium314.keyboard.settings.dialogs + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.material3.AlertDialog +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton +import androidx.compose.material3.TextField +import androidx.compose.material3.contentColorFor +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.input.KeyboardType +import androidx.compose.ui.text.input.TextFieldValue +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.window.DialogProperties +import helium314.keyboard.keyboard.internal.KeyboardIconsSet +import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyCode.checkAndConvertCode +import helium314.keyboard.latin.R +import helium314.keyboard.latin.settings.Settings +import helium314.keyboard.latin.utils.ToolbarKey +import helium314.keyboard.latin.utils.getCodeForToolbarKey +import helium314.keyboard.latin.utils.getCodeForToolbarKeyLongClick +import helium314.keyboard.latin.utils.getStringResourceOrName +import helium314.keyboard.latin.utils.readCustomKeyCodes +import helium314.keyboard.latin.utils.readCustomLongpressCodes +import helium314.keyboard.latin.utils.writeCustomKeyCodes +import helium314.keyboard.latin.utils.writeCustomLongpressCodes +import helium314.keyboard.settings.prefs +import helium314.keyboard.settings.screens.GetIcon + +// todo: +// reading and writing prefs should be done in the preference, or at least with the provided (single!) key +@Composable +fun ToolbarKeysCustomizer( + onDismissRequest: () -> Unit +) { + val ctx = LocalContext.current + var showKeyCustomizer: ToolbarKey? by remember { mutableStateOf(null) } + AlertDialog( + onDismissRequest = onDismissRequest, + confirmButton = { + TextButton(onClick = onDismissRequest) { Text(stringResource(R.string.dialog_close)) } + }, + dismissButton = { }, + title = { Text(stringResource(R.string.customize_toolbar_key_codes)) }, + text = { + LazyColumn { + items(ToolbarKey.entries) { + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier.clickable { showKeyCustomizer = it }.fillParentMaxWidth() + ) { + KeyboardIconsSet.instance.GetIcon(it.name) + Text(it.name.lowercase().getStringResourceOrName("", ctx).toString()) + } + } + } + }, + shape = MaterialTheme.shapes.medium, + containerColor = MaterialTheme.colorScheme.surface, + textContentColor = contentColorFor(MaterialTheme.colorScheme.surface), + properties = DialogProperties(), + ) + if (showKeyCustomizer != null) { + val shownKey = showKeyCustomizer + if (shownKey != null) + ToolbarKeyCustomizer(shownKey) { showKeyCustomizer = null } + } +} + +@Composable +private fun ToolbarKeyCustomizer( + key: ToolbarKey, + onDismissRequest: () -> Unit +) { + val ctx = LocalContext.current + val prefs = ctx.prefs() + var code by remember { mutableStateOf(TextFieldValue(getCodeForToolbarKey(key).toString())) } + var longPressCode by remember { mutableStateOf(TextFieldValue(getCodeForToolbarKeyLongClick(key).toString())) } + AlertDialog( + onDismissRequest = onDismissRequest, + confirmButton = { + TextButton( + onClick = { + writeCustomKeyCodes(prefs, readCustomKeyCodes(prefs) + (key.name to checkCode(code))) + writeCustomLongpressCodes(prefs, readCustomLongpressCodes(prefs) + (key.name to checkCode(longPressCode))) + onDismissRequest() + }, + enabled = checkCode(code) != null && checkCode(longPressCode) != null + ) { Text(stringResource(android.R.string.ok)) } + }, + dismissButton = { TextButton(onClick = onDismissRequest) { Text(stringResource(android.R.string.cancel)) } }, + title = { Text(key.name.lowercase().getStringResourceOrName("", ctx).toString()) }, + text = { + Column { + Row(verticalAlignment = Alignment.CenterVertically) { + Text(stringResource(R.string.key_code), Modifier.weight(0.5f)) + TextField( + value = code, + onValueChange = { code = it }, + keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number), + modifier = Modifier.weight(0.5f) + ) + } + Row(verticalAlignment = Alignment.CenterVertically) { + Text(stringResource(R.string.long_press_code), Modifier.weight(0.5f)) + TextField( + value = longPressCode, + onValueChange = { longPressCode = it }, + keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number), + modifier = Modifier.weight(0.5f) + ) + } + } + }, + shape = MaterialTheme.shapes.medium, + containerColor = MaterialTheme.colorScheme.surface, + textContentColor = contentColorFor(MaterialTheme.colorScheme.surface), + properties = DialogProperties(), + ) +} + +@Preview +@Composable +fun PreviewToolbarKeyCustomizer() { + Settings.init(LocalContext.current) + ToolbarKeyCustomizer(ToolbarKey.CUT) { } +} + +@Preview +@Composable +fun PreviewToolbarKeysCustomizer() { + Settings.init(LocalContext.current) + KeyboardIconsSet.instance.loadIcons(LocalContext.current) + ToolbarKeysCustomizer { } +} + +private fun checkCode(code: TextFieldValue) = runCatching { + code.text.toIntOrNull()?.takeIf { it.checkAndConvertCode() <= Char.MAX_VALUE.code } +}.getOrNull() diff --git a/app/src/main/java/helium314/keyboard/settings/screens/ToolbarScreen.kt b/app/src/main/java/helium314/keyboard/settings/screens/ToolbarScreen.kt index 300e43449..77241785a 100644 --- a/app/src/main/java/helium314/keyboard/settings/screens/ToolbarScreen.kt +++ b/app/src/main/java/helium314/keyboard/settings/screens/ToolbarScreen.kt @@ -41,6 +41,7 @@ import helium314.keyboard.settings.SettingsActivity2 import helium314.keyboard.settings.SwitchPreference import helium314.keyboard.settings.Theme import helium314.keyboard.settings.dialogs.ReorderDialog +import helium314.keyboard.settings.dialogs.ToolbarKeysCustomizer import helium314.keyboard.settings.prefs import helium314.keyboard.settings.themeChanged @@ -112,8 +113,11 @@ fun createToolbarPrefs(context: Context) = listOf( name = def.title, onClick = { showDialog = true }, ) - // todo: needs the dialog! - // which actually changes a different pref key... see if we can avoid it without too much work + if (showDialog) + // todo: CUSTOM_KEY_CODES vs the 2 actual prefs that are changed... + ToolbarKeysCustomizer( + onDismissRequest = { showDialog = false } + ) }, PrefDef(context, Settings.PREF_QUICK_PIN_TOOLBAR_KEYS, R.string.quick_pin_toolbar_keys, R.string.quick_pin_toolbar_keys_summary) { def -> SwitchPreference( @@ -168,7 +172,7 @@ fun ToolbarKeyReorderDialog( displayItem = { item -> var checked by remember { mutableStateOf(item.state) } Row(verticalAlignment = Alignment.CenterVertically) { - KeyboardIconsSet.instance.GetIcon(item.name.lowercase()) + KeyboardIconsSet.instance.GetIcon(item.name) val text = item.name.lowercase().getStringResourceOrName("", ctx).toString() Text(text, Modifier.weight(1f)) Switch( @@ -199,7 +203,7 @@ fun KeyboardIconsSet.GetIcon(name: String?) { val drawable = getNewDrawable(name, ctx) Box(Modifier.size(40.dp), contentAlignment = Alignment.Center) { if (drawable is VectorDrawable) - Icon(painterResource(iconIds[name]!!), null, Modifier.fillMaxSize(0.8f)) + Icon(painterResource(iconIds[name?.lowercase()]!!), null, Modifier.fillMaxSize(0.8f)) else if (drawable != null) { val px = TypedValueCompat.dpToPx(40f, ctx.resources.displayMetrics).toInt() Icon(drawable.toBitmap(px, px).asImageBitmap(), null, Modifier.fillMaxSize(0.8f))