From bf2f7cde500047ba439676b65969d75349586838 Mon Sep 17 00:00:00 2001 From: saravanakumardb1 Date: Sat, 28 Feb 2026 01:53:28 -0800 Subject: [PATCH] feat(wear): expand Wear OS with quick timer creation, timer detail, dismiss/snooze actions, navigation --- .../com/chronomind/wear/WearMainActivity.kt | 287 ++++++++++++++++-- 1 file changed, 254 insertions(+), 33 deletions(-) diff --git a/android/wear/src/main/java/com/chronomind/wear/WearMainActivity.kt b/android/wear/src/main/java/com/chronomind/wear/WearMainActivity.kt index 3040dee..24b1d00 100644 --- a/android/wear/src/main/java/com/chronomind/wear/WearMainActivity.kt +++ b/android/wear/src/main/java/com/chronomind/wear/WearMainActivity.kt @@ -26,46 +26,107 @@ class WearMainActivity : ComponentActivity() { } } +// ── Navigation State ───────────────────────────────────────── + +enum class WearScreen { TIMELINE, QUICK_TIMER, DETAIL } + @Composable fun WearApp() { + var currentScreen by remember { mutableStateOf(WearScreen.TIMELINE) } + var selectedTimer by remember { mutableStateOf(null) } + val timers = remember { mutableStateListOf() } + MaterialTheme( colors = Colors( - primary = Color(0xFF6C5CE7), + primary = Color(0xFF5B8DEE), secondary = Color(0xFF00D2FF), - background = Color(0xFF0A0A0F), - surface = Color(0xFF14141F), - error = Color(0xFFFF5252), + background = Color(0xFF0A0B0F), + surface = Color(0xFF1A1B26), + error = Color(0xFFFF4757), onPrimary = Color.White, onSecondary = Color.White, - onBackground = Color(0xFFEEEEFF), - onSurface = Color(0xFFEEEEFF), + onBackground = Color(0xFFE8ECF4), + onSurface = Color(0xFFE8ECF4), onError = Color.White, - onSurfaceVariant = Color(0xFFAAAACC), + onSurfaceVariant = Color(0xFF8B92A8), ) ) { - WearTimelineScreen() + when (currentScreen) { + WearScreen.TIMELINE -> WearTimelineScreen( + timers = timers, + onTimerClick = { timer -> + selectedTimer = timer + currentScreen = WearScreen.DETAIL + }, + onQuickTimerClick = { currentScreen = WearScreen.QUICK_TIMER } + ) + WearScreen.QUICK_TIMER -> WearQuickTimerScreen( + onCreateTimer = { timer -> + timers.add(timer) + currentScreen = WearScreen.TIMELINE + }, + onBack = { currentScreen = WearScreen.TIMELINE } + ) + WearScreen.DETAIL -> { + selectedTimer?.let { timer -> + WearTimerDetailScreen( + timer = timer, + onDismiss = { + timers.removeAll { it.id == timer.id } + currentScreen = WearScreen.TIMELINE + }, + onSnooze = { minutes -> + val idx = timers.indexOfFirst { it.id == timer.id } + if (idx >= 0) { + timers[idx] = timer.copy( + remainingSeconds = minutes * 60.0, + state = "snoozed" + ) + } + currentScreen = WearScreen.TIMELINE + }, + onBack = { currentScreen = WearScreen.TIMELINE } + ) + } ?: run { currentScreen = WearScreen.TIMELINE } + } + } } } -@Composable -fun WearTimelineScreen() { - val timers = remember { mutableStateListOf() } +// ── Timeline Screen ────────────────────────────────────────── +@Composable +fun WearTimelineScreen( + timers: List, + onTimerClick: (WearTimer) -> Unit, + onQuickTimerClick: () -> Unit +) { Scaffold( timeText = { TimeText() }, vignette = { Vignette(vignettePosition = VignettePosition.TopAndBottom) } ) { - if (timers.isEmpty()) { - WearEmptyState() - } else { - ScalingLazyColumn( - modifier = Modifier.fillMaxSize(), - horizontalAlignment = Alignment.CenterHorizontally - ) { + ScalingLazyColumn( + modifier = Modifier.fillMaxSize(), + horizontalAlignment = Alignment.CenterHorizontally + ) { + if (timers.isEmpty()) { + item { WearEmptyState() } + } else { items(timers) { timer -> - WearTimerChip(timer) + WearTimerChip(timer, onClick = { onTimerClick(timer) }) } } + // Quick timer button at bottom + item { + Spacer(modifier = Modifier.height(8.dp)) + CompactChip( + onClick = onQuickTimerClick, + label = { Text("+ Quick Timer", fontSize = 12.sp) }, + colors = ChipDefaults.chipColors( + backgroundColor = Color(0xFF5B8DEE) + ) + ) + } } } } @@ -99,11 +160,182 @@ private fun WearEmptyState() { } } +// ── Quick Timer Screen ─────────────────────────────────────── + @Composable -fun WearTimerChip(timer: WearTimer) { +fun WearQuickTimerScreen( + onCreateTimer: (WearTimer) -> Unit, + onBack: () -> Unit +) { + val presets = listOf( + "1 min" to 60.0, + "3 min" to 180.0, + "5 min" to 300.0, + "10 min" to 600.0, + "15 min" to 900.0, + "25 min" to 1500.0, + "30 min" to 1800.0, + "60 min" to 3600.0 + ) + + Scaffold( + timeText = { TimeText() }, + vignette = { Vignette(vignettePosition = VignettePosition.TopAndBottom) } + ) { + ScalingLazyColumn( + modifier = Modifier.fillMaxSize(), + horizontalAlignment = Alignment.CenterHorizontally + ) { + item { + Text( + text = "Quick Timer", + color = Color(0xFFE8ECF4), + fontSize = 16.sp, + fontWeight = FontWeight.Bold + ) + Spacer(modifier = Modifier.height(4.dp)) + } + + items(presets) { (label, seconds) -> + Chip( + modifier = Modifier.fillMaxWidth(), + onClick = { + onCreateTimer( + WearTimer( + id = java.util.UUID.randomUUID().toString(), + label = "Timer ($label)", + urgency = "standard", + remainingSeconds = seconds, + state = "active" + ) + ) + }, + label = { Text(label, fontSize = 14.sp) }, + colors = ChipDefaults.chipColors( + backgroundColor = Color(0xFF1A1B26) + ) + ) + } + + item { + Spacer(modifier = Modifier.height(4.dp)) + CompactChip( + onClick = onBack, + label = { Text("Cancel", fontSize = 12.sp) }, + colors = ChipDefaults.chipColors( + backgroundColor = Color(0xFF2A2D3A) + ) + ) + } + } + } +} + +// ── Timer Detail Screen ────────────────────────────────────── + +@Composable +fun WearTimerDetailScreen( + timer: WearTimer, + onDismiss: () -> Unit, + onSnooze: (Int) -> Unit, + onBack: () -> Unit +) { + Scaffold( + timeText = { TimeText() }, + vignette = { Vignette(vignettePosition = VignettePosition.TopAndBottom) } + ) { + ScalingLazyColumn( + modifier = Modifier.fillMaxSize(), + horizontalAlignment = Alignment.CenterHorizontally + ) { + item { + Text( + text = timer.label, + color = Color(0xFFE8ECF4), + fontSize = 16.sp, + fontWeight = FontWeight.Bold, + textAlign = TextAlign.Center + ) + Spacer(modifier = Modifier.height(8.dp)) + } + + item { + Text( + text = timer.formattedRemaining, + color = urgencyColor(timer.urgency), + fontSize = 36.sp, + fontWeight = FontWeight.Thin, + fontFamily = FontFamily.Monospace + ) + Spacer(modifier = Modifier.height(12.dp)) + } + + // Dismiss + item { + Chip( + modifier = Modifier.fillMaxWidth(), + onClick = onDismiss, + label = { Text("Dismiss", fontSize = 14.sp) }, + colors = ChipDefaults.chipColors( + backgroundColor = Color(0xFFFF4757) + ) + ) + } + + // Snooze options + item { + Chip( + modifier = Modifier.fillMaxWidth(), + onClick = { onSnooze(5) }, + label = { Text("Snooze 5 min", fontSize = 14.sp) }, + colors = ChipDefaults.chipColors( + backgroundColor = Color(0xFF2A2D3A) + ) + ) + } + item { + Chip( + modifier = Modifier.fillMaxWidth(), + onClick = { onSnooze(10) }, + label = { Text("Snooze 10 min", fontSize = 14.sp) }, + colors = ChipDefaults.chipColors( + backgroundColor = Color(0xFF2A2D3A) + ) + ) + } + + // Back + item { + Spacer(modifier = Modifier.height(4.dp)) + CompactChip( + onClick = onBack, + label = { Text("Back", fontSize = 12.sp) }, + colors = ChipDefaults.chipColors( + backgroundColor = Color(0xFF2A2D3A) + ) + ) + } + } + } +} + +private fun urgencyColor(urgency: String): Color { + return when (urgency) { + "critical" -> Color(0xFFFF4757) + "important" -> Color(0xFFFF9F43) + "gentle" -> Color(0xFF2ED573) + "passive" -> Color(0xFF8B92A8) + else -> Color(0xFF5B8DEE) + } +} + +// ── Timer Chip ─────────────────────────────────────────────── + +@Composable +fun WearTimerChip(timer: WearTimer, onClick: () -> Unit = {}) { Chip( modifier = Modifier.fillMaxWidth(), - onClick = { /* navigate to detail */ }, + onClick = onClick, label = { Text( text = timer.label, @@ -120,19 +352,8 @@ fun WearTimerChip(timer: WearTimer) { color = Color(0xFF6C5CE7) ) }, - icon = { - Text( - text = when (timer.urgency) { - "critical" -> "🔴" - "important" -> "🟠" - "gentle" -> "🟢" - else -> "🔵" - }, - fontSize = 16.sp - ) - }, colors = ChipDefaults.chipColors( - backgroundColor = Color(0xFF14141F) + backgroundColor = Color(0xFF1A1B26) ) ) }