diff --git a/app/src/main/java/com/bnyro/clock/ui/components/NumberKeypad.kt b/app/src/main/java/com/bnyro/clock/ui/components/NumberKeypad.kt index 0d472850..62fc25f6 100644 --- a/app/src/main/java/com/bnyro/clock/ui/components/NumberKeypad.kt +++ b/app/src/main/java/com/bnyro/clock/ui/components/NumberKeypad.kt @@ -38,28 +38,32 @@ fun NumberKeypad( verticalArrangement = Arrangement.spacedBy(buttonSpacing) ) { Row( - horizontalArrangement = Arrangement.spacedBy(buttonSpacing) + horizontalArrangement = Arrangement.spacedBy(buttonSpacing), + modifier = Modifier.weight(1f) ) { NumPadButton(number = "1", buttonSize, onOperation) NumPadButton(number = "2", buttonSize, onOperation) NumPadButton(number = "3", buttonSize, onOperation) } Row( - horizontalArrangement = Arrangement.spacedBy(buttonSpacing) + horizontalArrangement = Arrangement.spacedBy(buttonSpacing), + modifier = Modifier.weight(1f) ) { NumPadButton(number = "4", buttonSize, onOperation) NumPadButton(number = "5", buttonSize, onOperation) NumPadButton(number = "6", buttonSize, onOperation) } Row( - horizontalArrangement = Arrangement.spacedBy(buttonSpacing) + horizontalArrangement = Arrangement.spacedBy(buttonSpacing), + modifier = Modifier.weight(1f) ) { NumPadButton(number = "7", buttonSize, onOperation) NumPadButton(number = "8", buttonSize, onOperation) NumPadButton(number = "9", buttonSize, onOperation) } Row( - horizontalArrangement = Arrangement.spacedBy(buttonSpacing) + horizontalArrangement = Arrangement.spacedBy(buttonSpacing), + modifier = Modifier.weight(1f) ) { NumPadButton(number = "00", buttonSize, onOperation) NumPadButton(number = "0", buttonSize, onOperation) diff --git a/app/src/main/java/com/bnyro/clock/ui/screens/TimerScreen.kt b/app/src/main/java/com/bnyro/clock/ui/screens/TimerScreen.kt index 311c0aaf..2262b9a0 100644 --- a/app/src/main/java/com/bnyro/clock/ui/screens/TimerScreen.kt +++ b/app/src/main/java/com/bnyro/clock/ui/screens/TimerScreen.kt @@ -1,5 +1,6 @@ package com.bnyro.clock.ui.screens +import android.content.Context import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.background import androidx.compose.foundation.combinedClickable @@ -28,11 +29,15 @@ import androidx.compose.material.icons.filled.PlayArrow import androidx.compose.material.icons.filled.Save import androidx.compose.material.icons.rounded.Add import androidx.compose.material.icons.rounded.AddAlarm +import androidx.compose.material3.Button +import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.FloatingActionButton import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.ModalBottomSheet import androidx.compose.material3.SmallFloatingActionButton import androidx.compose.material3.Text +import androidx.compose.material3.rememberModalBottomSheetState import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue @@ -58,7 +63,7 @@ import com.bnyro.clock.ui.model.TimerModel import com.bnyro.clock.ui.nav.TopBarScaffold import com.bnyro.clock.util.Preferences -@OptIn(ExperimentalFoundationApi::class) +@OptIn(ExperimentalMaterial3Api::class) @Composable fun TimerScreen(onClickSettings: () -> Unit, timerModel: TimerModel) { val context = LocalContext.current @@ -72,129 +77,37 @@ fun TimerScreen(onClickSettings: () -> Unit, timerModel: TimerModel) { mutableStateOf(false) } - TopBarScaffold(title = stringResource(R.string.timer), onClickSettings, fab = { - if (timerModel.scheduledObjects.isEmpty() || createNew) { - Column( - horizontalAlignment = Alignment.CenterHorizontally + TopBarScaffold(title = stringResource(R.string.timer), onClickSettings, actions = { + if (timerModel.scheduledObjects.isEmpty()) { + ClickableIcon( + imageVector = Icons.Rounded.AddAlarm, + contentDescription = stringResource(R.string.add_preset_timer) ) { - if (timerModel.scheduledObjects.isNotEmpty()) { - SmallFloatingActionButton( - containerColor = MaterialTheme.colorScheme.tertiaryContainer, - onClick = { createNew = false } - ) { - Icon(imageVector = Icons.Default.ArrowBack, contentDescription = null) - } - Spacer(Modifier.height(8.dp)) - } - FloatingActionButton( - onClick = { - createNew = false - timerModel.startTimer(context) - } - ) { - Icon(imageVector = Icons.Default.PlayArrow, contentDescription = null) - } + timerModel.addPersistentTimer(timerModel.timePickerSeconds) } } else { - FloatingActionButton( - modifier = Modifier, - onClick = { createNew = true } - ) { - Icon(imageVector = Icons.Default.Create, contentDescription = null) - } - } - }, actions = { - if (timerModel.scheduledObjects.isEmpty() || createNew) { ClickableIcon( - imageVector = Icons.Rounded.AddAlarm, + imageVector = Icons.Rounded.Add, contentDescription = stringResource(R.string.add_preset_timer) ) { - timerModel.addPersistentTimer(timerModel.timePickerSeconds) + createNew = true } } }) { paddingValues -> - if (timerModel.scheduledObjects.isEmpty() || createNew) { + if (timerModel.scheduledObjects.isEmpty()) { Column( - modifier = Modifier - .fillMaxSize() - .padding(paddingValues), - horizontalAlignment = Alignment.CenterHorizontally + Modifier + .padding(paddingValues) ) { - if (!useScrollPicker) { - Row( - Modifier - .fillMaxWidth() - .weight(2f), - horizontalArrangement = Arrangement.Center, - verticalAlignment = Alignment.CenterVertically - ) { - TimePickerDial(timerModel) - } - } else { - Column( - modifier = Modifier.weight(3f), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.Center - ) { - FormattedTimerTime( - seconds = timerModel.timePickerFakeUnits, - modifier = Modifier.padding(bottom = 32.dp) - ) - NumberKeypad( - onOperation = { operation -> - when (operation) { - is NumberKeypadOperation.AddNumber -> timerModel.addNumber( - operation.number - ) - - is NumberKeypadOperation.Delete -> timerModel.deleteLastNumber() - is NumberKeypadOperation.Clear -> timerModel.clear() - } - } - ) - } - } - if (showExampleTimers) { - val haptic = LocalHapticFeedback.current - LazyVerticalGrid( - modifier = Modifier - .fillMaxWidth(), - columns = GridCells.Adaptive(100.dp), - contentPadding = PaddingValues(16.dp), - verticalArrangement = Arrangement.spacedBy(8.dp), - horizontalArrangement = Arrangement.spacedBy(8.dp) - ) { - itemsIndexed(items = timerModel.persistentTimers) { index, timer -> - Box( - modifier = Modifier - .clip(RoundedCornerShape(16.dp)) - .combinedClickable( - onClick = { - timerModel.timePickerSeconds = timer.seconds - createNew = false - timerModel.startTimer(context) - }, - onLongClick = { - haptic.performHapticFeedback( - HapticFeedbackType.LongPress - ) - timerModel.removePersistentTimer(index) - } - ) - .width(100.dp) - .background(MaterialTheme.colorScheme.secondaryContainer) - .padding(8.dp), - contentAlignment = Alignment.Center - ) { - Text( - timer.formattedTime, - style = MaterialTheme.typography.titleLarge, - color = MaterialTheme.colorScheme.onSecondaryContainer - ) - } - } + TimerPicker( + useScrollPicker, + timerModel, + showExampleTimers, + context, + onCreateNew = { + createNew = false } - } + ) } } else { LazyColumn( @@ -209,4 +122,120 @@ fun TimerScreen(onClickSettings: () -> Unit, timerModel: TimerModel) { } } } + + if (createNew) { + val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true) + ModalBottomSheet( + onDismissRequest = { createNew = false }, + sheetState = sheetState + ) { + TimerPicker( + useScrollPicker, + timerModel, + showExampleTimers, + context, + onCreateNew = { + createNew = false + } + ) + } + } +} + +@Composable +@OptIn(ExperimentalFoundationApi::class) +private fun TimerPicker( + useScrollPicker: Boolean, + timerModel: TimerModel, + showExampleTimers: Boolean, + context: Context, + onCreateNew: () -> Unit +) { + Column( + modifier = Modifier + .fillMaxSize(), + horizontalAlignment = Alignment.CenterHorizontally + ) { + if (!useScrollPicker) { + Row( + Modifier + .fillMaxWidth() + .weight(2f), + horizontalArrangement = Arrangement.Center, + verticalAlignment = Alignment.CenterVertically + ) { + TimePickerDial(timerModel) + } + } else { + Column( + modifier = Modifier.weight(3f), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center + ) { + FormattedTimerTime( + seconds = timerModel.timePickerFakeUnits, + modifier = Modifier.padding(bottom = 32.dp) + ) + NumberKeypad( + onOperation = { operation -> + when (operation) { + is NumberKeypadOperation.AddNumber -> timerModel.addNumber( + operation.number + ) + + is NumberKeypadOperation.Delete -> timerModel.deleteLastNumber() + is NumberKeypadOperation.Clear -> timerModel.clear() + } + } + ) + } + } + if (showExampleTimers) { + val haptic = LocalHapticFeedback.current + LazyVerticalGrid( + modifier = Modifier + .fillMaxWidth(), + columns = GridCells.Adaptive(100.dp), + contentPadding = PaddingValues(16.dp), + verticalArrangement = Arrangement.spacedBy(8.dp), + horizontalArrangement = Arrangement.spacedBy(8.dp) + ) { + itemsIndexed(items = timerModel.persistentTimers) { index, timer -> + Box( + modifier = Modifier + .clip(RoundedCornerShape(16.dp)) + .combinedClickable( + onClick = { + timerModel.timePickerSeconds = timer.seconds + onCreateNew.invoke() + timerModel.startTimer(context) + }, + onLongClick = { + haptic.performHapticFeedback( + HapticFeedbackType.LongPress + ) + timerModel.removePersistentTimer(index) + } + ) + .width(100.dp) + .background(MaterialTheme.colorScheme.secondaryContainer) + .padding(8.dp), + contentAlignment = Alignment.Center + ) { + Text( + timer.formattedTime, + style = MaterialTheme.typography.titleLarge, + color = MaterialTheme.colorScheme.onSecondaryContainer + ) + } + } + } + } + Button(modifier = Modifier.padding(vertical = 16.dp), onClick = { + onCreateNew.invoke() + timerModel.startTimer(context) + }) { + Text(text = stringResource(R.string.start), style = MaterialTheme.typography.titleLarge) + } + } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 419c4c46..0186c981 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -109,4 +109,5 @@ Lap Time Overall Time Add preset timer + Start \ No newline at end of file