mirror of
https://github.com/Helium314/HeliBoard.git
synced 2025-04-19 13:49:13 +00:00
complete preferences screen
This commit is contained in:
parent
8f5ef56f60
commit
ae461fe8b6
4 changed files with 205 additions and 83 deletions
|
@ -31,17 +31,22 @@ import androidx.compose.ui.Alignment
|
|||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.Hyphens
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.core.content.edit
|
||||
import helium314.keyboard.keyboard.internal.KeyboardIconsSet
|
||||
import helium314.keyboard.latin.R
|
||||
import helium314.keyboard.latin.utils.Log
|
||||
import helium314.keyboard.latin.utils.getActivity
|
||||
import helium314.keyboard.latin.utils.getStringResourceOrName
|
||||
import helium314.keyboard.latin.utils.prefs
|
||||
import helium314.keyboard.settings.dialogs.ListPickerDialog
|
||||
import helium314.keyboard.settings.dialogs.ReorderDialog
|
||||
import helium314.keyboard.settings.dialogs.SliderDialog
|
||||
import helium314.keyboard.settings.screens.GetIcon
|
||||
|
||||
// taken from StreetComplete (and a bit SCEE)
|
||||
|
||||
|
@ -256,6 +261,91 @@ fun <T: Any> ListPreference(
|
|||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ReorderSwitchPreference(def: PrefDef, default: String) {
|
||||
var showDialog by remember { mutableStateOf(false) }
|
||||
Preference(
|
||||
name = def.title,
|
||||
description = def.description,
|
||||
onClick = { showDialog = true },
|
||||
)
|
||||
if (showDialog) {
|
||||
val ctx = LocalContext.current
|
||||
val prefs = ctx.prefs()
|
||||
val items = prefs.getString(def.key, default)!!.split(";").mapTo(ArrayList()) {
|
||||
val both = it.split(",")
|
||||
KeyAndState(both.first(), both.last().toBoolean())
|
||||
}
|
||||
ReorderDialog(
|
||||
onConfirmed = { reorderedItems ->
|
||||
val value = reorderedItems.joinToString(";") { it.name + "," + it.state }
|
||||
prefs.edit().putString(def.key, value).apply()
|
||||
keyboardNeedsReload = true
|
||||
},
|
||||
onDismissRequest = { showDialog = false },
|
||||
onNeutral = { prefs.edit().remove(def.key).apply() },
|
||||
neutralButtonText = if (prefs.contains(def.key)) stringResource(R.string.button_default) else null,
|
||||
items = items,
|
||||
title = { Text(def.title) },
|
||||
displayItem = { item ->
|
||||
var checked by remember { mutableStateOf(item.state) }
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
KeyboardIconsSet.instance.GetIcon(item.name)
|
||||
val text = item.name.lowercase().getStringResourceOrName("", ctx)
|
||||
Text(text, Modifier.weight(1f))
|
||||
Switch(
|
||||
checked = checked,
|
||||
onCheckedChange = { item.state = it; checked = it }
|
||||
)
|
||||
}
|
||||
},
|
||||
getKey = { it.name }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ToolbarKeyReorderDialog(
|
||||
prefKey: String,
|
||||
default: String,
|
||||
title: String,
|
||||
onDismiss: () -> Unit
|
||||
) {
|
||||
val ctx = LocalContext.current
|
||||
val prefs = ctx.prefs()
|
||||
val items = prefs.getString(prefKey, default)!!.split(";").mapTo(ArrayList()) {
|
||||
val both = it.split(",")
|
||||
KeyAndState(both.first(), both.last().toBoolean())
|
||||
}
|
||||
ReorderDialog(
|
||||
onConfirmed = { reorderedItems ->
|
||||
val value = reorderedItems.joinToString(";") { it.name + "," + it.state }
|
||||
prefs.edit().putString(prefKey, value).apply()
|
||||
keyboardNeedsReload = true
|
||||
},
|
||||
onDismissRequest = onDismiss,
|
||||
onNeutral = { prefs.edit().remove(prefKey).apply() },
|
||||
neutralButtonText = if (prefs.contains(prefKey)) stringResource(R.string.button_default) else null,
|
||||
items = items,
|
||||
title = { Text(title) },
|
||||
displayItem = { item ->
|
||||
var checked by remember { mutableStateOf(item.state) }
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
KeyboardIconsSet.instance.GetIcon(item.name)
|
||||
val text = item.name.lowercase().getStringResourceOrName("", ctx)
|
||||
Text(text, Modifier.weight(1f))
|
||||
Switch(
|
||||
checked = checked,
|
||||
onCheckedChange = { item.state = it; checked = it }
|
||||
)
|
||||
}
|
||||
},
|
||||
getKey = { it.name }
|
||||
)
|
||||
}
|
||||
|
||||
private class KeyAndState(var name: String, var state: Boolean)
|
||||
|
||||
private fun <T: Any> getPrefOfType(prefs: SharedPreferences, key: String, default: T): T =
|
||||
when (default) {
|
||||
is String -> prefs.getString(key, default)
|
||||
|
|
|
@ -15,7 +15,6 @@ import kotlinx.coroutines.flow.MutableStateFlow
|
|||
|
||||
// todo (roughly in order)
|
||||
// make all prefs actually work
|
||||
// preferences
|
||||
// advanced (not much)
|
||||
// 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)
|
||||
|
@ -23,12 +22,12 @@ import kotlinx.coroutines.flow.MutableStateFlow
|
|||
// more similar dialog style args (for all dialogs, or for none)
|
||||
// check whether dialogs have the same colors, i think currently it's a bit inconsistent
|
||||
// see all the properties for each alertDialog -> any way to set it in a single place?
|
||||
// yes/no/default can now be confirmDialog
|
||||
// title too huge for bg image and text on spacebar dialogs, also maybe somewhere else -> where to set in one place?
|
||||
// check dark and light theme (don't have dynamic)
|
||||
// rename both settingsActivities
|
||||
// work on todos in other files
|
||||
// calling KeyboardSwitcher.getInstance().forceUpdateKeyboardTheme(requireContext()) while keyboard is showing shows just full screen background
|
||||
// but reload while keyboard is showing would be great (isn't it at least semi-done when changing one-handed mode?)
|
||||
// use better / more structured and clear names and arrangement of files
|
||||
// the prefDef and AllPrefs, also be clear about pref <-> key <-> prefKey (all used, probably should be latter)
|
||||
// there is a lot more ambiguous naming...
|
||||
|
@ -64,6 +63,7 @@ import kotlinx.coroutines.flow.MutableStateFlow
|
|||
// color settings (should at least change how colors are stored, and have a color search/filter)
|
||||
// allow users to add custom themes instead of only having a single one (maybe also switchable in colors settings)
|
||||
// one single place for default values (to be used in composables and settings)
|
||||
// does it make sense to put this into PrefDef?
|
||||
// make auto_correct_threshold a float directly with the list pref (needs pref upgrade)
|
||||
// using context.prefs() outside settings
|
||||
// merge PREF_TOOLBAR_CUSTOM_KEY_CODES and PREF_TOOLBAR_CUSTOM_LONGPRESS_CODES into one pref (don't forget settings upgrade)
|
||||
|
|
|
@ -4,18 +4,34 @@ import android.content.Context
|
|||
import android.media.AudioManager
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import helium314.keyboard.keyboard.KeyboardLayoutSet
|
||||
import helium314.keyboard.latin.AudioAndHapticFeedbackManager
|
||||
import helium314.keyboard.latin.R
|
||||
import helium314.keyboard.latin.settings.Settings
|
||||
import helium314.keyboard.latin.utils.Log
|
||||
import helium314.keyboard.latin.utils.POPUP_KEYS_LABEL_DEFAULT
|
||||
import helium314.keyboard.latin.utils.POPUP_KEYS_ORDER_DEFAULT
|
||||
import helium314.keyboard.latin.utils.getActivity
|
||||
import helium314.keyboard.latin.utils.getEnabledSubtypes
|
||||
import helium314.keyboard.latin.utils.locale
|
||||
import helium314.keyboard.latin.utils.prefs
|
||||
import helium314.keyboard.settings.AllPrefs
|
||||
import helium314.keyboard.settings.ListPreference
|
||||
import helium314.keyboard.settings.PrefDef
|
||||
import helium314.keyboard.settings.PreferenceCategory
|
||||
import helium314.keyboard.settings.ReorderSwitchPreference
|
||||
import helium314.keyboard.settings.SearchPrefScreen
|
||||
import helium314.keyboard.settings.SettingsActivity2
|
||||
import helium314.keyboard.settings.SliderPreference
|
||||
import helium314.keyboard.settings.SwitchPreference
|
||||
import helium314.keyboard.settings.Theme
|
||||
import helium314.keyboard.settings.keyboardNeedsReload
|
||||
|
||||
@Composable
|
||||
fun PreferencesScreen(
|
||||
|
@ -25,13 +41,100 @@ fun PreferencesScreen(
|
|||
onClickBack = onClickBack,
|
||||
title = stringResource(R.string.settings_screen_preferences),
|
||||
) {
|
||||
SettingsActivity2.allPrefs.map[Settings.PREF_CLIPBOARD_HISTORY_RETENTION_TIME]!!.Preference()
|
||||
val prefs = LocalContext.current.prefs()
|
||||
val b = (LocalContext.current.getActivity() as? SettingsActivity2)?.prefChanged?.collectAsState()
|
||||
if ((b?.value ?: 0) < 0)
|
||||
Log.v("irrelevant", "stupid way to trigger recomposition on preference change")
|
||||
PreferenceCategory(stringResource(R.string.settings_category_input)) {
|
||||
SettingsActivity2.allPrefs.map[Settings.PREF_SHOW_HINTS]!!.Preference()
|
||||
if (prefs.getBoolean(Settings.PREF_SHOW_HINTS, true))
|
||||
SettingsActivity2.allPrefs.map[Settings.PREF_POPUP_KEYS_LABELS_ORDER]!!.Preference()
|
||||
SettingsActivity2.allPrefs.map[Settings.PREF_POPUP_KEYS_ORDER]!!.Preference()
|
||||
SettingsActivity2.allPrefs.map[Settings.PREF_SHOW_POPUP_HINTS]!!.Preference()
|
||||
SettingsActivity2.allPrefs.map[Settings.PREF_POPUP_ON]!!.Preference()
|
||||
SettingsActivity2.allPrefs.map[Settings.PREF_VIBRATE_ON]!!.Preference()
|
||||
if (prefs.getBoolean(Settings.PREF_VIBRATE_ON, true))
|
||||
SettingsActivity2.allPrefs.map[Settings.PREF_VIBRATION_DURATION_SETTINGS]!!.Preference()
|
||||
if (prefs.getBoolean(Settings.PREF_VIBRATE_ON, true))
|
||||
SettingsActivity2.allPrefs.map[Settings.PREF_VIBRATE_IN_DND_MODE]!!.Preference()
|
||||
SettingsActivity2.allPrefs.map[Settings.PREF_SOUND_ON]!!.Preference()
|
||||
if (prefs.getBoolean(Settings.PREF_SOUND_ON, true))
|
||||
SettingsActivity2.allPrefs.map[Settings.PREF_KEYPRESS_SOUND_VOLUME]!!.Preference()
|
||||
SettingsActivity2.allPrefs.map[Settings.PREF_CLIPBOARD_HISTORY_RETENTION_TIME]!!.Preference()
|
||||
}
|
||||
PreferenceCategory(stringResource(R.string.settings_category_additional_keys)) {
|
||||
SettingsActivity2.allPrefs.map[Settings.PREF_SHOW_NUMBER_ROW]!!.Preference()
|
||||
if (getEnabledSubtypes(prefs, true).any { it.locale().language in localesWithLocalizedNumberRow })
|
||||
SettingsActivity2.allPrefs.map[Settings.PREF_LOCALIZED_NUMBER_ROW]!!.Preference()
|
||||
SettingsActivity2.allPrefs.map[Settings.PREF_SHOW_LANGUAGE_SWITCH_KEY]!!.Preference()
|
||||
SettingsActivity2.allPrefs.map[Settings.PREF_LANGUAGE_SWITCH_KEY]!!.Preference()
|
||||
SettingsActivity2.allPrefs.map[Settings.PREF_SHOW_EMOJI_KEY]!!.Preference()
|
||||
SettingsActivity2.allPrefs.map[Settings.PREF_REMOVE_REDUNDANT_POPUPS]!!.Preference()
|
||||
}
|
||||
PreferenceCategory(stringResource(R.string.settings_category_clipboard_history)) {
|
||||
SettingsActivity2.allPrefs.map[Settings.PREF_ENABLE_CLIPBOARD_HISTORY]!!.Preference()
|
||||
if (prefs.getBoolean(Settings.PREF_ENABLE_CLIPBOARD_HISTORY, true))
|
||||
SettingsActivity2.allPrefs.map[Settings.PREF_CLIPBOARD_HISTORY_RETENTION_TIME]!!.Preference()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun createPreferencesPrefs(context: Context) = listOf(
|
||||
PrefDef(context, Settings.PREF_SHOW_HINTS, R.string.show_hints, R.string.show_hints_summary) {
|
||||
SwitchPreference(it, true)
|
||||
},
|
||||
PrefDef(context, Settings.PREF_POPUP_KEYS_LABELS_ORDER, R.string.hint_source) {
|
||||
ReorderSwitchPreference(it, POPUP_KEYS_LABEL_DEFAULT)
|
||||
},
|
||||
PrefDef(context, Settings.PREF_POPUP_KEYS_ORDER, R.string.popup_order) {
|
||||
ReorderSwitchPreference(it, POPUP_KEYS_ORDER_DEFAULT)
|
||||
},
|
||||
PrefDef(context, Settings.PREF_SHOW_POPUP_HINTS, R.string.show_popup_hints, R.string.show_popup_hints_summary) {
|
||||
SwitchPreference(it, false) { keyboardNeedsReload = true }
|
||||
},
|
||||
PrefDef(context, Settings.PREF_POPUP_ON, R.string.popup_on_keypress) {
|
||||
val dm = LocalContext.current.resources.displayMetrics
|
||||
val px600 = with(LocalDensity.current) { 600.dp.toPx() }
|
||||
SwitchPreference(it, dm.widthPixels >= px600 || dm.heightPixels >= px600)
|
||||
},
|
||||
PrefDef(context, Settings.PREF_VIBRATE_ON, R.string.vibrate_on_keypress) {
|
||||
SwitchPreference(it, false)
|
||||
},
|
||||
PrefDef(context, Settings.PREF_VIBRATE_IN_DND_MODE, R.string.vibrate_in_dnd_mode) {
|
||||
SwitchPreference(it, false)
|
||||
},
|
||||
PrefDef(context, Settings.PREF_SOUND_ON, R.string.sound_on_keypress) {
|
||||
SwitchPreference(it, false)
|
||||
},
|
||||
PrefDef(context, Settings.PREF_ENABLE_CLIPBOARD_HISTORY, R.string.enable_clipboard_history, R.string.enable_clipboard_history_summary) {
|
||||
SwitchPreference(it, true)
|
||||
},
|
||||
PrefDef(context, Settings.PREF_SHOW_NUMBER_ROW, R.string.number_row, R.string.number_row_summary) {
|
||||
SwitchPreference(it, false) { keyboardNeedsReload = true }
|
||||
},
|
||||
PrefDef(context, Settings.PREF_LOCALIZED_NUMBER_ROW, R.string.localized_number_row, R.string.localized_number_row_summary) {
|
||||
SwitchPreference(it, true) { KeyboardLayoutSet.onSystemLocaleChanged() }
|
||||
},
|
||||
PrefDef(context, Settings.PREF_SHOW_LANGUAGE_SWITCH_KEY, R.string.show_language_switch_key) {
|
||||
SwitchPreference(it, false) { keyboardNeedsReload = true }
|
||||
},
|
||||
PrefDef(context, Settings.PREF_LANGUAGE_SWITCH_KEY, R.string.language_switch_key_behavior) {
|
||||
ListPreference(
|
||||
it,
|
||||
listOf(
|
||||
"internal" to stringResource(R.string.switch_language),
|
||||
"input_method" to stringResource(R.string.language_switch_key_switch_input_method),
|
||||
"both" to stringResource(R.string.language_switch_key_switch_both)
|
||||
),
|
||||
"internal"
|
||||
) { keyboardNeedsReload = true }
|
||||
},
|
||||
PrefDef(context, Settings.PREF_SHOW_EMOJI_KEY, R.string.show_emoji_key) {
|
||||
SwitchPreference(it, false)
|
||||
},
|
||||
PrefDef(context, Settings.PREF_REMOVE_REDUNDANT_POPUPS, R.string.remove_redundant_popups, R.string.remove_redundant_popups_summary) {
|
||||
SwitchPreference(it, false) { keyboardNeedsReload = true }
|
||||
},
|
||||
PrefDef(context, Settings.PREF_CLIPBOARD_HISTORY_RETENTION_TIME, R.string.clipboard_history_retention_time) { def ->
|
||||
SliderPreference(
|
||||
name = def.title,
|
||||
|
@ -73,6 +176,9 @@ fun createPreferencesPrefs(context: Context) = listOf(
|
|||
},
|
||||
)
|
||||
|
||||
// todo: not good to have it hardcoded, but reading a bunch of files may be noticeably slow
|
||||
private val localesWithLocalizedNumberRow = listOf("ar", "bn", "fa", "gu", "hi", "kn", "mr", "ne", "ur")
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
private fun Preview() {
|
||||
|
|
|
@ -37,6 +37,7 @@ import helium314.keyboard.settings.AllPrefs
|
|||
import helium314.keyboard.settings.NonSettingsPrefs
|
||||
import helium314.keyboard.settings.PrefDef
|
||||
import helium314.keyboard.settings.Preference
|
||||
import helium314.keyboard.settings.ReorderSwitchPreference
|
||||
import helium314.keyboard.settings.SearchPrefScreen
|
||||
import helium314.keyboard.settings.SettingsActivity2
|
||||
import helium314.keyboard.settings.SwitchPreference
|
||||
|
@ -66,46 +67,13 @@ fun ToolbarScreen(
|
|||
|
||||
fun createToolbarPrefs(context: Context) = listOf(
|
||||
PrefDef(context, Settings.PREF_TOOLBAR_KEYS, R.string.toolbar_keys) { def ->
|
||||
var showDialog by remember { mutableStateOf(false) }
|
||||
Preference(
|
||||
name = def.title,
|
||||
onClick = { showDialog = true },
|
||||
)
|
||||
if (showDialog) {
|
||||
ToolbarKeyReorderDialog(
|
||||
def.key,
|
||||
defaultToolbarPref,
|
||||
def.title,
|
||||
) { showDialog = false }
|
||||
}
|
||||
ReorderSwitchPreference(def, defaultToolbarPref)
|
||||
},
|
||||
PrefDef(context, Settings.PREF_PINNED_TOOLBAR_KEYS, R.string.pinned_toolbar_keys) { def ->
|
||||
var showDialog by remember { mutableStateOf(false) }
|
||||
Preference(
|
||||
name = def.title,
|
||||
onClick = { showDialog = true },
|
||||
)
|
||||
if (showDialog) {
|
||||
ToolbarKeyReorderDialog(
|
||||
def.key,
|
||||
defaultPinnedToolbarPref,
|
||||
def.title,
|
||||
) { showDialog = false }
|
||||
}
|
||||
ReorderSwitchPreference(def, defaultPinnedToolbarPref)
|
||||
},
|
||||
PrefDef(context, Settings.PREF_CLIPBOARD_TOOLBAR_KEYS, R.string.clipboard_toolbar_keys) { def ->
|
||||
var showDialog by remember { mutableStateOf(false) }
|
||||
Preference(
|
||||
name = def.title,
|
||||
onClick = { showDialog = true },
|
||||
)
|
||||
if (showDialog) {
|
||||
ToolbarKeyReorderDialog(
|
||||
def.key,
|
||||
defaultClipboardToolbarPref,
|
||||
def.title,
|
||||
) { showDialog = false }
|
||||
}
|
||||
ReorderSwitchPreference(def, defaultClipboardToolbarPref)
|
||||
},
|
||||
PrefDef(context, NonSettingsPrefs.CUSTOM_KEY_CODES, R.string.customize_toolbar_key_codes) { def ->
|
||||
var showDialog by remember { mutableStateOf(false) }
|
||||
|
@ -145,48 +113,6 @@ fun createToolbarPrefs(context: Context) = listOf(
|
|||
}
|
||||
)
|
||||
|
||||
@Composable
|
||||
fun ToolbarKeyReorderDialog(
|
||||
prefKey: String,
|
||||
default: String,
|
||||
title: String,
|
||||
onDismiss: () -> Unit
|
||||
) {
|
||||
val ctx = LocalContext.current
|
||||
val prefs = ctx.prefs()
|
||||
val items = prefs.getString(prefKey, default)!!.split(";").mapTo(ArrayList()) {
|
||||
val both = it.split(",")
|
||||
KeyAndState(both.first(), both.last().toBoolean())
|
||||
}
|
||||
ReorderDialog(
|
||||
onConfirmed = { reorderedItems ->
|
||||
val value = reorderedItems.joinToString(";") { it.name + "," + it.state }
|
||||
prefs.edit().putString(prefKey, value).apply()
|
||||
keyboardNeedsReload = true
|
||||
},
|
||||
onDismissRequest = onDismiss,
|
||||
onNeutral = { prefs.edit().remove(prefKey).apply() },
|
||||
neutralButtonText = if (prefs.contains(prefKey)) stringResource(R.string.button_default) else null,
|
||||
items = items,
|
||||
title = { Text(title) },
|
||||
displayItem = { item ->
|
||||
var checked by remember { mutableStateOf(item.state) }
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
KeyboardIconsSet.instance.GetIcon(item.name)
|
||||
val text = item.name.lowercase().getStringResourceOrName("", ctx)
|
||||
Text(text, Modifier.weight(1f))
|
||||
Switch(
|
||||
checked = checked,
|
||||
onCheckedChange = { item.state = it; checked = it }
|
||||
)
|
||||
}
|
||||
},
|
||||
getKey = { it.name }
|
||||
)
|
||||
}
|
||||
|
||||
private class KeyAndState(var name: String, var state: Boolean)
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
private fun Preview() {
|
||||
|
|
Loading…
Add table
Reference in a new issue