feat(wear): expand Wear OS with quick timer creation, timer detail, dismiss/snooze actions, navigation

This commit is contained in:
saravanakumardb1 2026-02-28 01:53:28 -08:00
parent 3ac658a89e
commit bf2f7cde50

View File

@ -26,46 +26,107 @@ class WearMainActivity : ComponentActivity() {
} }
} }
// ── Navigation State ─────────────────────────────────────────
enum class WearScreen { TIMELINE, QUICK_TIMER, DETAIL }
@Composable @Composable
fun WearApp() { fun WearApp() {
var currentScreen by remember { mutableStateOf(WearScreen.TIMELINE) }
var selectedTimer by remember { mutableStateOf<WearTimer?>(null) }
val timers = remember { mutableStateListOf<WearTimer>() }
MaterialTheme( MaterialTheme(
colors = Colors( colors = Colors(
primary = Color(0xFF6C5CE7), primary = Color(0xFF5B8DEE),
secondary = Color(0xFF00D2FF), secondary = Color(0xFF00D2FF),
background = Color(0xFF0A0A0F), background = Color(0xFF0A0B0F),
surface = Color(0xFF14141F), surface = Color(0xFF1A1B26),
error = Color(0xFFFF5252), error = Color(0xFFFF4757),
onPrimary = Color.White, onPrimary = Color.White,
onSecondary = Color.White, onSecondary = Color.White,
onBackground = Color(0xFFEEEEFF), onBackground = Color(0xFFE8ECF4),
onSurface = Color(0xFFEEEEFF), onSurface = Color(0xFFE8ECF4),
onError = Color.White, 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 // ── Timeline Screen ──────────────────────────────────────────
fun WearTimelineScreen() {
val timers = remember { mutableStateListOf<WearTimer>() }
@Composable
fun WearTimelineScreen(
timers: List<WearTimer>,
onTimerClick: (WearTimer) -> Unit,
onQuickTimerClick: () -> Unit
) {
Scaffold( Scaffold(
timeText = { TimeText() }, timeText = { TimeText() },
vignette = { Vignette(vignettePosition = VignettePosition.TopAndBottom) } vignette = { Vignette(vignettePosition = VignettePosition.TopAndBottom) }
) { ) {
if (timers.isEmpty()) { ScalingLazyColumn(
WearEmptyState() modifier = Modifier.fillMaxSize(),
} else { horizontalAlignment = Alignment.CenterHorizontally
ScalingLazyColumn( ) {
modifier = Modifier.fillMaxSize(), if (timers.isEmpty()) {
horizontalAlignment = Alignment.CenterHorizontally item { WearEmptyState() }
) { } else {
items(timers) { timer -> 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 @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( Chip(
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
onClick = { /* navigate to detail */ }, onClick = onClick,
label = { label = {
Text( Text(
text = timer.label, text = timer.label,
@ -120,19 +352,8 @@ fun WearTimerChip(timer: WearTimer) {
color = Color(0xFF6C5CE7) color = Color(0xFF6C5CE7)
) )
}, },
icon = {
Text(
text = when (timer.urgency) {
"critical" -> "🔴"
"important" -> "🟠"
"gentle" -> "🟢"
else -> "🔵"
},
fontSize = 16.sp
)
},
colors = ChipDefaults.chipColors( colors = ChipDefaults.chipColors(
backgroundColor = Color(0xFF14141F) backgroundColor = Color(0xFF1A1B26)
) )
) )
} }