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
fun WearApp() {
var currentScreen by remember { mutableStateOf(WearScreen.TIMELINE) }
var selectedTimer by remember { mutableStateOf<WearTimer?>(null) }
val timers = remember { mutableStateListOf<WearTimer>() }
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<WearTimer>() }
// ── Timeline Screen ──────────────────────────────────────────
@Composable
fun WearTimelineScreen(
timers: List<WearTimer>,
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
) {
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 = { /* navigate to detail */ },
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 = 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)
)
)
}