diff --git a/replica/uhr/clone-screens/S06-analog-light.png b/replica/uhr/clone-screens/S06-analog-light.png index bbb9679..b23945f 100644 Binary files a/replica/uhr/clone-screens/S06-analog-light.png and b/replica/uhr/clone-screens/S06-analog-light.png differ diff --git a/replica/uhr/clone-screens/S06-clock-dark.png b/replica/uhr/clone-screens/S06-clock-dark.png index 0b79b7d..2662dcf 100644 Binary files a/replica/uhr/clone-screens/S06-clock-dark.png and b/replica/uhr/clone-screens/S06-clock-dark.png differ diff --git a/replica/uhr/clone-screens/S11-ringing.png b/replica/uhr/clone-screens/S11-ringing.png index 03e5165..d8ce79f 100644 Binary files a/replica/uhr/clone-screens/S11-ringing.png and b/replica/uhr/clone-screens/S11-ringing.png differ diff --git a/uhr/app/build.gradle.kts b/uhr/app/build.gradle.kts index 0c2bc29..440bce3 100644 --- a/uhr/app/build.gradle.kts +++ b/uhr/app/build.gradle.kts @@ -16,8 +16,8 @@ android { applicationId = "app.uhr" minSdk = 29 targetSdk = 36 - versionCode = 1 - versionName = "0.1.0" + versionCode = 2 + versionName = "0.1.1" } // Release key lives outside the repo; without it, release builds fall back to the debug key (local only). diff --git a/uhr/app/src/main/java/app/uhr/ui/screens/AlarmScreen.kt b/uhr/app/src/main/java/app/uhr/ui/screens/AlarmScreen.kt index 3bb6c8f..96c2546 100644 --- a/uhr/app/src/main/java/app/uhr/ui/screens/AlarmScreen.kt +++ b/uhr/app/src/main/java/app/uhr/ui/screens/AlarmScreen.kt @@ -306,22 +306,49 @@ fun soundName(uri: String?): String { } } -/** S03: M3 time picker with dial/keyboard switch. */ +/** + * S03: M3 time picker with dial/keyboard switch. The Compose dial has no haptics; like the original we tick + * on every value the hand passes and give a firmer click when it settles after release. + */ @OptIn(ExperimentalMaterial3Api::class) @Composable fun TimeDialog(hour: Int, minute: Int, onDismiss: () -> Unit, onPick: (Int, Int) -> Unit) { val state = rememberTimePickerState(hour, minute, Fmt.is24h) var keyboard by remember { mutableStateOf(false) } + val view = androidx.compose.ui.platform.LocalView.current + androidx.compose.runtime.LaunchedEffect(state) { + var last = state.hour to state.minute + androidx.compose.runtime.snapshotFlow { state.hour to state.minute }.collect { now -> + if (now != last) { + view.performHapticFeedback(android.view.HapticFeedbackConstants.CLOCK_TICK) + last = now + } + } + } + // the dial switches from hours to minutes when the hour settles: confirm that with a firmer click + androidx.compose.runtime.LaunchedEffect(state) { + var hourMode = state.selection == androidx.compose.material3.TimePickerSelectionMode.Hour + androidx.compose.runtime.snapshotFlow { state.selection }.collect { sel -> + val nowHour = sel == androidx.compose.material3.TimePickerSelectionMode.Hour + if (hourMode && !nowHour) view.performHapticFeedback(android.view.HapticFeedbackConstants.CONFIRM) + hourMode = nowHour + } + } AlertDialog( onDismissRequest = onDismiss, title = { Text(stringResource(R.string.pick_time)) }, text = { - Column(horizontalAlignment = Alignment.CenterHorizontally) { + Column(horizontalAlignment = Alignment.CenterHorizontally, modifier = Modifier.fillMaxWidth()) { if (keyboard) TimeInput(state) else TimePicker(state) TextButton(onClick = { keyboard = !keyboard }) { Text(stringResource(if (keyboard) R.string.use_dial else R.string.use_keyboard)) } } }, - confirmButton = { TextButton(onClick = { onPick(state.hour, state.minute) }) { Text(stringResource(android.R.string.ok)) } }, + confirmButton = { + TextButton(onClick = { + view.performHapticFeedback(android.view.HapticFeedbackConstants.CONFIRM) + onPick(state.hour, state.minute) + }) { Text(stringResource(android.R.string.ok)) } + }, dismissButton = { TextButton(onClick = onDismiss) { Text(stringResource(android.R.string.cancel)) } }, ) } diff --git a/uhr/app/src/main/java/app/uhr/ui/theme/Theme.kt b/uhr/app/src/main/java/app/uhr/ui/theme/Theme.kt index 2493bbe..9a81077 100644 --- a/uhr/app/src/main/java/app/uhr/ui/theme/Theme.kt +++ b/uhr/app/src/main/java/app/uhr/ui/theme/Theme.kt @@ -37,7 +37,8 @@ private val Dark = darkColorScheme( ) private val AppTypography = Typography( - displayLarge = WType.clockBig, headlineLarge = WType.headline, titleLarge = WType.title, + // displayLarge/headline stay M3 defaults: the time picker uses them for its hour and minute fields + titleLarge = WType.title, bodyLarge = WType.body, bodyMedium = WType.bodySm, labelLarge = WType.label, labelMedium = WType.label, labelSmall = WType.labelSm, )