gioser

sergio/humanoid

HTML 13TOML 10 Sutichaykuna

⎇ 5227fbf1abfb2a437968ebc63692560c3a929230 keyboard/src/main/java/com/rizoma/trazo/data/TrazoSettings.kt 78 siq'ikuna · 3.4 KB Ñawpa willay ch'uya

fix: agregar imports faltantes (offset, getValue) y corregir CenterVertical/updateHaptics 6f37139d5 · Sergio ·

1package com.rizoma.trazo.data
2
3import android.content.Context
4import androidx.compose.runtime.getValue
5import androidx.compose.runtime.mutableStateOf
6import androidx.compose.runtime.setValue
7import androidx.datastore.core.DataStore
8import androidx.datastore.preferences.core.MutablePreferences
9import androidx.datastore.preferences.core.Preferences
10import androidx.datastore.preferences.core.booleanPreferencesKey
11import androidx.datastore.preferences.core.edit
12import androidx.datastore.preferences.core.stringPreferencesKey
13import androidx.datastore.preferences.preferencesDataStore
14import kotlinx.coroutines.CoroutineScope
15import kotlinx.coroutines.Dispatchers
16import kotlinx.coroutines.launch
17
18/** Intensidad del retorno háptico al teclear. */
19enum class HapticLevel { SUAVE, MEDIO, FUERTE }
20
21private val Context.trazoSettingsStore: DataStore<Preferences> by preferencesDataStore(name = "trazo_settings")
22
23/**
24 * Preferencias de Trazo, persistidas en DataStore y expuestas como estado de Compose.
25 * Un único colector mantiene en sincronía cualquier instancia (la del IME y la de la
26 * pantalla de ajustes), así que tocar un toggle se refleja al instante en el teclado.
27 */
28class TrazoSettings(context: Context, private val scope: CoroutineScope) {
29
30    private val store = context.applicationContext.trazoSettingsStore
31
32    var haptics by mutableStateOf(true); private set
33    var hapticLevel by mutableStateOf(HapticLevel.MEDIO); private set
34    var doubleSpacePeriod by mutableStateOf(true); private set
35    var spanish by mutableStateOf(true); private set
36    var english by mutableStateOf(true); private set
37    var recentEmojis by mutableStateOf<List<String>>(emptyList()); private set
38
39    init {
40        scope.launch {
41            store.data.collect { p ->
42                haptics = p[HAPTICS] ?: true
43                hapticLevel = runCatching { HapticLevel.valueOf(p[HAPTIC_LEVEL] ?: "") }
44                    .getOrDefault(HapticLevel.MEDIO)
45                doubleSpacePeriod = p[DOUBLE_SPACE] ?: true
46                spanish = p[LANG_ES] ?: true
47                english = p[LANG_EN] ?: true
48                recentEmojis = p[RECENT_EMOJIS]?.split(" ")?.filter { it.isNotEmpty() } ?: emptyList()
49            }
50        }
51    }
52
53    fun updateHaptics(v: Boolean) = persist { it[HAPTICS] = v }
54    fun updateHapticLevel(v: HapticLevel) = persist { it[HAPTIC_LEVEL] = v.name }
55    fun updateDoubleSpacePeriod(v: Boolean) = persist { it[DOUBLE_SPACE] = v }
56    fun updateSpanish(v: Boolean) = persist { it[LANG_ES] = v }
57    fun updateEnglish(v: Boolean) = persist { it[LANG_EN] = v }
58
59    /** Empuja un emoji a la cabeza de "recientes" (sin duplicar, acotado). */
60    fun pushRecentEmoji(e: String) {
61        val updated = (listOf(e) + recentEmojis.filter { it != e }).take(RECENTS_MAX)
62        persist { it[RECENT_EMOJIS] = updated.joinToString(" ") }
63    }
64
65    private fun persist(block: (MutablePreferences) -> Unit) {
66        scope.launch(Dispatchers.IO) { runCatching { store.edit(block) } }
67    }
68
69    private companion object {
70        val HAPTICS = booleanPreferencesKey("haptics")
71        val HAPTIC_LEVEL = stringPreferencesKey("haptic_level")
72        val DOUBLE_SPACE = booleanPreferencesKey("double_space_period")
73        val LANG_ES = booleanPreferencesKey("lang_es")
74        val LANG_EN = booleanPreferencesKey("lang_en")
75        val RECENT_EMOJIS = stringPreferencesKey("recent_emojis")
76        const val RECENTS_MAX = 24
77    }
78}