tawasuyu

sergio/humanoid

HTML 38Markdown 1TOML 10 Sutichaykuna

⎇ 5227fbf1abfb2a437968ebc63692560c3a929230 keyboard/src/main/java/com/rizoma/trazo/MainActivity.kt 201 siq'ikuna · 7.3 KB Ñawpa willay ch'uya

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

1package com.rizoma.trazo
2
3import android.content.Context
4import android.content.Intent
5import android.os.Bundle
6import android.provider.Settings
7import android.view.inputmethod.InputMethodManager
8import androidx.activity.ComponentActivity
9import androidx.activity.compose.setContent
10import androidx.compose.foundation.background
11import androidx.compose.foundation.border
12import androidx.compose.foundation.clickable
13import androidx.compose.foundation.layout.Arrangement
14import androidx.compose.foundation.layout.Box
15import androidx.compose.foundation.layout.Column
16import androidx.compose.foundation.layout.Row
17import androidx.compose.foundation.layout.Spacer
18import androidx.compose.foundation.layout.fillMaxSize
19import androidx.compose.foundation.layout.fillMaxWidth
20import androidx.compose.foundation.layout.height
21import androidx.compose.foundation.layout.padding
22import androidx.compose.foundation.layout.width
23import androidx.compose.foundation.rememberScrollState
24import androidx.compose.foundation.shape.RoundedCornerShape
25import androidx.compose.foundation.verticalScroll
26import androidx.compose.material3.Text
27import androidx.compose.runtime.Composable
28import androidx.compose.ui.Alignment
29import androidx.compose.ui.Modifier
30import androidx.compose.ui.draw.clip
31import androidx.compose.ui.graphics.Color
32import androidx.compose.ui.text.font.FontWeight
33import androidx.compose.ui.unit.dp
34import androidx.compose.ui.unit.sp
35import androidx.core.view.WindowCompat
36import androidx.lifecycle.lifecycleScope
37import com.rizoma.trazo.data.HapticLevel
38import com.rizoma.trazo.data.TrazoSettings
39import com.rizoma.trazo.ui.theme.NeonCian
40import com.rizoma.trazo.ui.theme.NeonRosa
41import com.rizoma.trazo.ui.theme.NeonVerde
42import com.rizoma.trazo.ui.theme.Tecla
43import com.rizoma.trazo.ui.theme.Tenue
44import com.rizoma.trazo.ui.theme.TrazoTheme
45import com.rizoma.trazo.ui.theme.Vacio
46
47/** Pantalla para activar Trazo, elegirlo como teclado y ajustar sus preferencias. */
48class MainActivity : ComponentActivity() {
49
50    private lateinit var settings: TrazoSettings
51
52    override fun onCreate(savedInstanceState: Bundle?) {
53        super.onCreate(savedInstanceState)
54        settings = TrazoSettings(this, lifecycleScope)
55        WindowCompat.setDecorFitsSystemWindows(window, false)
56        setContent {
57            TrazoTheme {
58                Setup(
59                    settings = settings,
60                    onActivar = { startActivity(Intent(Settings.ACTION_INPUT_METHOD_SETTINGS)) },
61                    onElegir = {
62                        (getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager)
63                            .showInputMethodPicker()
64                    },
65                )
66            }
67        }
68    }
69}
70
71@Composable
72private fun Setup(settings: TrazoSettings, onActivar: () -> Unit, onElegir: () -> Unit) {
73    Column(
74        Modifier
75            .fillMaxSize()
76            .background(Vacio)
77            .verticalScroll(rememberScrollState())
78            .padding(horizontal = 32.dp, vertical = 56.dp),
79    ) {
80        Text("Trazo", color = NeonVerde, fontSize = 44.sp, fontWeight = FontWeight.Light)
81        Spacer(Modifier.height(8.dp))
82        Text("teclado de trazos — un toque, ocho gestos.", color = Tenue, fontSize = 15.sp)
83        Spacer(Modifier.height(36.dp))
84
85        Paso("1", "activa Trazo en ajustes del sistema", NeonCian, onActivar)
86        Spacer(Modifier.height(16.dp))
87        Paso("2", "elígelo como teclado actual", NeonRosa, onElegir)
88
89        Spacer(Modifier.height(40.dp))
90        Seccion("ajustes")
91        Spacer(Modifier.height(12.dp))
92
93        Toggle("vibración al teclear", settings.haptics, NeonCian) { settings.updateHaptics(it) }
94        if (settings.haptics) {
95            Spacer(Modifier.height(10.dp))
96            NivelHaptico(settings.hapticLevel) { settings.updateHapticLevel(it) }
97        }
98
99        Spacer(Modifier.height(10.dp))
100        Toggle("doble espacio → punto", settings.doubleSpacePeriod, NeonVerde) {
101            settings.updateDoubleSpacePeriod(it)
102        }
103
104        Spacer(Modifier.height(24.dp))
105        Seccion("idiomas de predicción")
106        Spacer(Modifier.height(12.dp))
107        Toggle("español", settings.spanish, NeonRosa) { settings.updateSpanish(it) }
108        Spacer(Modifier.height(10.dp))
109        Toggle("inglés", settings.english, NeonCian) { settings.updateEnglish(it) }
110    }
111}
112
113@Composable
114private fun Seccion(titulo: String) {
115    Text(titulo, color = Tenue, fontSize = 13.sp, fontWeight = FontWeight.Medium)
116}
117
118@Composable
119private fun Paso(num: String, label: String, accent: Color, onClick: () -> Unit) {
120    Column(
121        Modifier
122            .fillMaxWidth()
123            .clip(RoundedCornerShape(18.dp))
124            .background(Tecla)
125            .border(1.dp, accent.copy(alpha = 0.4f), RoundedCornerShape(18.dp))
126            .clickable(onClick = onClick)
127            .padding(20.dp),
128    ) {
129        Text(num, color = accent, fontSize = 13.sp, fontWeight = FontWeight.Bold)
130        Spacer(Modifier.height(6.dp))
131        Text(label, color = Color.White, fontSize = 17.sp)
132    }
133}
134
135@Composable
136private fun Toggle(label: String, value: Boolean, accent: Color, onChange: (Boolean) -> Unit) {
137    Row(
138        Modifier
139            .fillMaxWidth()
140            .clip(RoundedCornerShape(14.dp))
141            .background(Tecla)
142            .clickable { onChange(!value) }
143            .padding(horizontal = 18.dp, vertical = 16.dp),
144        verticalAlignment = Alignment.CenterVertically,
145    ) {
146        Text(label, color = Color.White, fontSize = 16.sp, modifier = Modifier.weight(1f))
147        Pill(value, accent)
148    }
149}
150
151/** Indicador tipo interruptor: relleno y a la derecha cuando está activo. */
152@Composable
153private fun Pill(on: Boolean, accent: Color) {
154    Box(
155        Modifier
156            .width(46.dp)
157            .height(26.dp)
158            .clip(RoundedCornerShape(13.dp))
159            .background(if (on) accent.copy(alpha = 0.28f) else Color(0xFF1B1B26))
160            .border(1.dp, if (on) accent else Tenue, RoundedCornerShape(13.dp)),
161        contentAlignment = if (on) Alignment.CenterEnd else Alignment.CenterStart,
162    ) {
163        Box(
164            Modifier
165                .padding(3.dp)
166                .width(20.dp)
167                .height(20.dp)
168                .clip(RoundedCornerShape(10.dp))
169                .background(if (on) accent else Tenue),
170        )
171    }
172}
173
174@Composable
175private fun NivelHaptico(level: HapticLevel, onSelect: (HapticLevel) -> Unit) {
176    Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(8.dp)) {
177        HapticLevel.entries.forEach { opt ->
178            val selected = opt == level
179            Box(
180                Modifier
181                    .weight(1f)
182                    .clip(RoundedCornerShape(12.dp))
183                    .background(if (selected) NeonCian.copy(alpha = 0.18f) else Tecla)
184                    .border(
185                        1.dp,
186                        if (selected) NeonCian else Tenue.copy(alpha = 0.4f),
187                        RoundedCornerShape(12.dp),
188                    )
189                    .clickable { onSelect(opt) }
190                    .padding(vertical = 12.dp),
191                contentAlignment = Alignment.Center,
192            ) {
193                Text(
194                    text = opt.name.lowercase(),
195                    color = if (selected) NeonCian else Tenue,
196                    fontSize = 14.sp,
197                )
198            }
199        }
200    }
201}