mirror of
https://gitlab.futo.org/keyboard/latinime.git
synced 2024-09-28 14:54:30 +01:00
Add slider for long press duration
This commit is contained in:
parent
abda1a3d08
commit
49cbcabf5e
@ -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()
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
@ -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
|
||||
)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user