1package com.peachpasswords.ui.components23import androidx.compose.animation.animateColorAsState4import androidx.compose.foundation.layout.Row5import androidx.compose.material3.Text6import androidx.compose.runtime.Composable7import androidx.compose.runtime.getValue8import androidx.compose.runtime.mutableIntStateOf9import androidx.compose.runtime.remember10import androidx.compose.runtime.setValue11import androidx.compose.ui.Modifier12import androidx.compose.ui.graphics.Shadow13import androidx.compose.ui.text.TextStyle14import androidx.compose.ui.text.font.FontStyle15import androidx.compose.ui.unit.sp16import com.peachpasswords.ui.theme.LocalPeachAccent17import com.peachpasswords.ui.theme.LocalReduceMotion18import com.peachpasswords.ui.theme.peachColors19import com.peachpasswords.ui.theme.PeachType20import kotlinx.coroutines.delay21import androidx.compose.runtime.LaunchedEffect22import kotlin.random.Random2324private const val RUNE_COUNT = 925262728293031@Composable32fun LockRuneString(modifier: Modifier = Modifier) {33 val accent = LocalPeachAccent.current34 val reduceMotion = LocalReduceMotion.current35 val runes = remember {36 (0 until RUNE_COUNT).map { (0xE000 + Random.nextInt(256)).toChar().toString() }37 }38 var glowIdx by remember { mutableIntStateOf(-1) }3940 if (!reduceMotion) {41 LaunchedEffect(Unit) {42 while (true) {43 delay(1500L + Random.nextLong(3000))44 glowIdx = Random.nextInt(RUNE_COUNT)45 delay(2000L + Random.nextLong(1500))46 glowIdx = -147 }48 }49 }5051 Row(modifier = modifier) {52 runes.forEachIndexed { idx, ch ->53 val glowing = idx == glowIdx54 val color by animateColorAsState(55 targetValue = if (glowing) accent else peachColors.T0.copy(alpha = 0.12f),56 label = "rune-glow",57 )58 Text(59 text = ch,60 color = color,61 style = TextStyle(62 fontFamily = PeachType.Script,63 fontStyle = FontStyle.Normal,64 fontSize = 13.sp,65 shadow = if (glowing) Shadow(color = accent, blurRadius = 12f) else null,66 ),67 )68 }69 }70}