Add slider for long press duration

This commit is contained in:
Aleksandras Kostarevas 2024-05-08 13:02:36 -05:00
parent abda1a3d08
commit 49cbcabf5e
3 changed files with 138 additions and 20 deletions

View File

@ -23,7 +23,6 @@ import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material.icons.filled.ArrowForward
import androidx.compose.material.icons.filled.Send
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.RadioButton
@ -48,6 +47,7 @@ import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.focus.onFocusChanged
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.graphics.drawscope.translate
import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.platform.LocalContext
@ -58,9 +58,7 @@ import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.navigation.NavHostController
import androidx.navigation.compose.rememberNavController
import kotlinx.coroutines.runBlocking
import org.futo.inputmethod.latin.uix.SettingsKey
import org.futo.inputmethod.latin.uix.getSetting
import org.futo.inputmethod.latin.uix.getSettingBlocking
import org.futo.inputmethod.latin.uix.theme.Typography
import kotlin.math.pow
@ -268,20 +266,22 @@ fun<T> SettingRadio(
}
@Composable
fun<T: Number> SettingSlider(
private fun<T: Number> SettingSliderForDataStoreItem(
title: String,
setting: SettingsKey<T>,
item: DataStoreItem<T>,
default: T,
range: ClosedFloatingPointRange<Float>,
transform: (Float) -> T,
indicator: (T) -> String = { it.toString() },
hardRange: ClosedFloatingPointRange<Float> = range,
power: Float = 1.0f,
subtitle: String? = null
subtitle: String? = null,
steps: Int = 0,
) {
val context = LocalContext.current
val (value, setValue) = useDataStore(key = setting.key, default = setting.default)
var virtualValue by remember { mutableFloatStateOf((runBlocking { context.getSetting(setting) }).toFloat().let {
val (value, setValue) = item
var virtualValue by remember { mutableFloatStateOf(value.toFloat().let {
if(it == Float.POSITIVE_INFINITY || it == Float.NEGATIVE_INFINITY) {
it
} else {
@ -317,7 +317,7 @@ fun<T: Number> SettingSlider(
val newValue = if (number != null) {
transform(number.coerceIn(hardRange))
} else {
setting.default
default
}
setValue(newValue)
@ -327,12 +327,13 @@ fun<T: Number> SettingSlider(
textFieldValue = TextFieldValue()
}
}
BasicTextField(
value = textFieldValue,
onValueChange = { textFieldValue = it },
modifier = Modifier
.weight(0.33f)
.align(Alignment.CenterVertically)
.align(CenterVertically)
.focusRequester(focusRequester)
.onFocusChanged {
if (it.isFocused) hasTextFieldFocusedYet = true
@ -345,9 +346,9 @@ fun<T: Number> SettingSlider(
}
),
singleLine = true,
textStyle = Typography.labelMedium
textStyle = Typography.labelMedium.copy(color = MaterialTheme.colorScheme.onBackground),
cursorBrush = SolidColor(MaterialTheme.colorScheme.primary)
)
} else {
Text(
text = indicator(value),
@ -368,12 +369,68 @@ fun<T: Number> SettingSlider(
setValue(transform(it.pow(power))) },
valueRange = range.start.pow(1.0f / power) .. range.endInclusive.pow(1.0f / power),
enabled = !isTextFieldVisible,
modifier = Modifier.weight(1.0f)
modifier = Modifier.weight(1.0f),
steps = steps
)
}
}
}
@Composable
fun<T: Number> SettingSlider(
title: String,
setting: SettingsKey<T>,
range: ClosedFloatingPointRange<Float>,
transform: (Float) -> T,
indicator: (T) -> String = { it.toString() },
hardRange: ClosedFloatingPointRange<Float> = range,
power: Float = 1.0f,
subtitle: String? = null,
steps: Int = 0
) {
SettingSliderForDataStoreItem(
title = title,
item = useDataStore(setting),
default = setting.default,
range = range,
transform = transform,
indicator = indicator,
hardRange = hardRange,
power = power,
subtitle = subtitle,
steps = steps
)
}
@Composable
fun SettingSliderSharedPrefsInt(
title: String,
key: String,
default: Int,
range: ClosedFloatingPointRange<Float>,
transform: (Float) -> Int,
indicator: (Int) -> String = { it.toString() },
hardRange: ClosedFloatingPointRange<Float> = range,
power: Float = 1.0f,
subtitle: String? = null,
steps: Int = 0
) {
SettingSliderForDataStoreItem(
title = title,
item = useSharedPrefsInt(key, default),
default = default,
range = range,
transform = transform,
indicator = indicator,
hardRange = hardRange,
power = power,
subtitle = subtitle,
steps = steps
)
}
@Composable
fun ScrollableList(content: @Composable () -> Unit) {
val scrollState = rememberScrollState()

View File

@ -4,6 +4,7 @@ import android.content.SharedPreferences
import android.preference.PreferenceManager
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
@ -80,19 +81,19 @@ fun <T> useDataStore(key: SettingsKey<T>): DataStoreItem<T> {
}
@Composable
fun useSharedPrefsBool(key: String, default: Boolean): DataStoreItem<Boolean> {
fun<T> useSharedPrefsGeneric(key: String, default: T, get: (SharedPreferences, String, T) -> T, put: (SharedPreferences, String, T) -> Unit): DataStoreItem<T> {
val coroutineScope = rememberCoroutineScope()
val context = LocalContext.current
val sharedPrefs = remember { PreferenceManager.getDefaultSharedPreferences(context) }
val value = remember { mutableStateOf(sharedPrefs.getBoolean(key, default)) }
val value = remember { mutableStateOf(get(sharedPrefs, key, default)) }
// This is not the most efficient way to do this... but it works for a settings menu
DisposableEffect(Unit) {
val listener =
SharedPreferences.OnSharedPreferenceChangeListener { sharedPreferences, changedKey ->
if (key == changedKey) {
value.value = sharedPreferences.getBoolean(key, value.value)
value.value = get(sharedPreferences, key, value.value)
}
}
@ -103,15 +104,63 @@ fun useSharedPrefsBool(key: String, default: Boolean): DataStoreItem<Boolean> {
}
}
val setValue = { newValue: Boolean ->
val setValue = { newValue: T ->
coroutineScope.launch {
withContext(Dispatchers.Main) {
sharedPrefs.edit {
putBoolean(key, newValue)
}
put(sharedPrefs, key, newValue)
}
}
}
return DataStoreItem(value.value, setValue)
}
@Composable
fun useSharedPrefsBool(key: String, default: Boolean): DataStoreItem<Boolean> {
return useSharedPrefsGeneric(key, default,
get = { sharedPreferences, k, d ->
sharedPreferences.getBoolean(k, d)
},
put = { sharedPreferences, k, v ->
sharedPreferences.edit {
putBoolean(k, v)
}
}
)
}
@Composable
fun useSharedPrefsInt(key: String, default: Int): DataStoreItem<Int> {
return useSharedPrefsGeneric(key, default,
get = { sharedPreferences, k, d ->
sharedPreferences.getInt(k, d)
},
put = { sharedPreferences, k, v ->
sharedPreferences.edit {
putInt(k, v)
}
}
)
}
@Composable
private fun<T> SyncDataStoreToPreferences(key: SettingsKey<T>, update: (newValue: T, editor: SharedPreferences.Editor) -> Unit) {
val context = LocalContext.current
val sharedPrefs = remember { PreferenceManager.getDefaultSharedPreferences(context) }
val value = useDataStoreValueBlocking(key)
LaunchedEffect(value) {
val edit = sharedPrefs.edit {
update(value, this)
}
}
}
@Composable
fun SyncDataStoreToPreferencesInt(key: SettingsKey<Int>, sharedPreference: String) {
SyncDataStoreToPreferences(key) { value, editor ->
editor.putInt(sharedPreference, value)
}
}

View File

@ -21,6 +21,7 @@ import org.futo.inputmethod.latin.uix.SettingsKey
import org.futo.inputmethod.latin.uix.settings.ScreenTitle
import org.futo.inputmethod.latin.uix.settings.ScrollableList
import org.futo.inputmethod.latin.uix.settings.SettingSlider
import org.futo.inputmethod.latin.uix.settings.SettingSliderSharedPrefsInt
import org.futo.inputmethod.latin.uix.settings.SettingToggleDataStore
import org.futo.inputmethod.latin.uix.settings.SettingToggleSharedPrefs
import org.futo.inputmethod.latin.uix.settings.useDataStore
@ -107,5 +108,16 @@ fun TypingScreen(navController: NavHostController = rememberNavController()) {
}
}
)
SettingSliderSharedPrefsInt(
title = "Long Press Duration",
key = Settings.PREF_KEY_LONGPRESS_TIMEOUT,
default = 300,
range = 100.0f .. 700.0f,
hardRange = 25.0f .. 1200.0f,
transform = { it.roundToInt() },
indicator = { "$it ms" },
steps = 23
)
}
}