1package com.peachpasswords.ui.components23import androidx.compose.animation.core.RepeatMode4import androidx.compose.animation.core.animateFloat5import androidx.compose.animation.core.infiniteRepeatable6import androidx.compose.animation.core.rememberInfiniteTransition7import androidx.compose.animation.core.tween8import androidx.compose.animation.animateColorAsState9import androidx.compose.foundation.background10import androidx.compose.foundation.layout.Box11import androidx.compose.foundation.layout.size12import androidx.compose.foundation.shape.CircleShape13import androidx.compose.runtime.Composable14import androidx.compose.runtime.getValue15import androidx.compose.ui.Modifier16import androidx.compose.ui.draw.alpha17import androidx.compose.ui.draw.clip18import androidx.compose.ui.semantics.contentDescription19import androidx.compose.ui.semantics.semantics20import androidx.compose.ui.unit.Dp21import androidx.compose.ui.unit.dp22import com.peachpasswords.sync.SyncIndicator23import com.peachpasswords.ui.theme.LocalReduceMotion24import com.peachpasswords.ui.theme.peachColors2526272829303132333435@Composable36fun SyncIndicatorDot(37 indicator: SyncIndicator,38 label: String,39 modifier: Modifier = Modifier,40 size: Dp = 6.dp,41) {42 val color by animateColorAsState(43 targetValue = when (indicator) {44 45 46 SyncIndicator.BUSY, SyncIndicator.OK -> peachColors.SyncOk47 SyncIndicator.WARN -> peachColors.SyncWarn48 SyncIndicator.ERROR -> peachColors.SyncErr49 SyncIndicator.IDLE -> peachColors.T250 },51 label = "sync-indicator",52 )53 val pulsing = indicator == SyncIndicator.BUSY && !LocalReduceMotion.current54 val alpha = if (pulsing) {55 val transition = rememberInfiniteTransition(label = "sync-pulse")56 val value by transition.animateFloat(57 initialValue = 1f,58 targetValue = 0.3f,59 animationSpec = infiniteRepeatable(60 animation = tween(900),61 repeatMode = RepeatMode.Reverse,62 ),63 label = "sync-pulse-alpha",64 )65 value66 } else {67 1f68 }69 Box(70 modifier71 .size(size)72 .alpha(alpha)73 .clip(CircleShape)74 .background(color)75 .semantics { contentDescription = label },76 )77}