⎇ 5227fbf1abfb2a437968ebc63692560c3a929230
keyboard/src/main/java/com/rizoma/trazo/data/TrazoSettings.kt
Ñawpa willay
ch'uya
fix: agregar imports faltantes (offset, getValue) y corregir CenterVertical/updateHaptics
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}