From 25cbd8253466c66ae79cad791326f1ae7d3e7743 Mon Sep 17 00:00:00 2001 From: Sad Ellie Date: Mon, 9 Oct 2023 12:40:07 +0300 Subject: [PATCH] Move date time pickers --- .../DatePickerDialog.kt} | 139 +-------------- .../common/datetimepicker/TimePickerDialog.kt | 162 ++++++++++++++++++ .../components/DateTimeDialogs.kt | 4 +- .../unitto/feature/timezone/TimeZoneScreen.kt | 2 +- 4 files changed, 172 insertions(+), 135 deletions(-) rename core/ui/src/main/java/com/sadellie/unitto/core/ui/common/{DateTimePickerDialog.kt => datetimepicker/DatePickerDialog.kt} (59%) create mode 100644 core/ui/src/main/java/com/sadellie/unitto/core/ui/common/datetimepicker/TimePickerDialog.kt diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/DateTimePickerDialog.kt b/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/datetimepicker/DatePickerDialog.kt similarity index 59% rename from core/ui/src/main/java/com/sadellie/unitto/core/ui/common/DateTimePickerDialog.kt rename to core/ui/src/main/java/com/sadellie/unitto/core/ui/common/datetimepicker/DatePickerDialog.kt index debca4a7..444c9093 100644 --- a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/DateTimePickerDialog.kt +++ b/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/datetimepicker/DatePickerDialog.kt @@ -16,60 +16,33 @@ * along with this program. If not, see . */ -package com.sadellie.unitto.core.ui.common +package com.sadellie.unitto.core.ui.common.datetimepicker -import android.text.format.DateFormat -import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.IntrinsicSize import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.requiredWidth -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.wrapContentHeight -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.outlined.Keyboard -import androidx.compose.material.icons.outlined.Schedule import androidx.compose.material3.AlertDialog import androidx.compose.material3.DatePicker import androidx.compose.material3.DatePickerDefaults -import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.material3.TextButton -import androidx.compose.material3.TimeInput -import androidx.compose.material3.TimePicker import androidx.compose.material3.rememberDatePickerState -import androidx.compose.material3.rememberTimePickerState import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.saveable.rememberSaveable -import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.layout.Layout import androidx.compose.ui.layout.Placeable -import androidx.compose.ui.platform.LocalConfiguration -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource -import androidx.compose.ui.semantics.isTraversalGroup -import androidx.compose.ui.semantics.semantics import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.compose.ui.window.DialogProperties -import androidx.compose.ui.zIndex import com.sadellie.unitto.core.base.R import java.time.Instant import java.time.LocalDateTime @@ -77,106 +50,6 @@ import java.time.ZoneId import java.time.ZonedDateTime import kotlin.math.max -// https://cs.android.com/androidx/platform/tools/dokka-devsite-plugin/+/master:testData/compose/samples/material3/samples/TimePickerSamples.kt -@Composable -fun TimePickerDialog( - hour: Int, - minute: Int, - onCancel: () -> Unit, - onConfirm: (hour: Int, minute: Int) -> Unit, - confirmLabel: String = stringResource(R.string.ok_label), -) { - val pickerState = rememberTimePickerState( - initialHour = hour, - initialMinute = minute, - is24Hour = DateFormat.is24HourFormat(LocalContext.current) - ) - val configuration = LocalConfiguration.current - var showingPicker by rememberSaveable { mutableStateOf(true) } - - AlertDialog( - onDismissRequest = onCancel, - properties = DialogProperties( - usePlatformDefaultWidth = false - ), - ) { - Surface( - shape = MaterialTheme.shapes.extraLarge, - tonalElevation = 6.dp, - modifier = Modifier - .width(IntrinsicSize.Min) - .height(IntrinsicSize.Min) - .background( - shape = MaterialTheme.shapes.extraLarge, - color = MaterialTheme.colorScheme.surface - ), - ) { - if (configuration.screenHeightDp > 400) { - // Make this take the entire viewport. This will guarantee that Screen readers - // focus the toggle first. - Box( - Modifier - .fillMaxSize() - .semantics { - isTraversalGroup = true - } - ) { - IconButton( - modifier = Modifier - // This is a workaround so that the Icon comes up first - // in the talkback traversal order. So that users of a11y - // services can use the text input. When talkback traversal - // order is customizable we can remove this. - .size(64.dp, 72.dp) - .align(Alignment.BottomStart) - .zIndex(5f), - onClick = { showingPicker = !showingPicker }) { - val icon = if (showingPicker) { - Icons.Outlined.Keyboard - } else { - Icons.Outlined.Schedule - } - Icon( - imageVector = icon, - contentDescription = stringResource(R.string.select_time_label) - ) - } - } - } - Column( - modifier = Modifier.padding(24.dp), - horizontalAlignment = Alignment.CenterHorizontally - ) { - Text( - modifier = Modifier - .fillMaxWidth() - .padding(bottom = 20.dp), - text = stringResource(R.string.select_time_label), - style = MaterialTheme.typography.labelMedium - ) - if (showingPicker && configuration.screenHeightDp > 400) { - TimePicker(state = pickerState) - } else { - TimeInput(state = pickerState) - } - Row( - modifier = Modifier - .height(40.dp) - .fillMaxWidth() - ) { - Spacer(modifier = Modifier.weight(1f)) - TextButton( - onClick = onCancel - ) { Text(stringResource(R.string.cancel_label)) } - TextButton( - onClick = { onConfirm(pickerState.hour, pickerState.minute) } - ) { Text(confirmLabel) } - } - } - } - } -} - @Composable fun DatePickerDialog( modifier: Modifier = Modifier, @@ -204,9 +77,11 @@ fun DatePickerDialog( Column(verticalArrangement = Arrangement.SpaceBetween) { DatePicker(state = pickerState) - Box(modifier = Modifier - .align(Alignment.End) - .padding(_dialogButtonsPadding)) { + Box( + modifier = Modifier + .align(Alignment.End) + .padding(_dialogButtonsPadding) + ) { AlertDialogFlowRow( mainAxisSpacing = _dialogButtonsMainAxisSpacing, @@ -332,4 +207,4 @@ private fun AlertDialogFlowRow( private val _dialogButtonsPadding by lazy { PaddingValues(bottom = 8.dp, end = 6.dp) } private val _dialogButtonsMainAxisSpacing by lazy { 8.dp } -private val _dialogButtonsCrossAxisSpacing by lazy { 12.dp } +private val _dialogButtonsCrossAxisSpacing by lazy { 12.dp } \ No newline at end of file diff --git a/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/datetimepicker/TimePickerDialog.kt b/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/datetimepicker/TimePickerDialog.kt new file mode 100644 index 00000000..20f56364 --- /dev/null +++ b/core/ui/src/main/java/com/sadellie/unitto/core/ui/common/datetimepicker/TimePickerDialog.kt @@ -0,0 +1,162 @@ +/* + * Unitto is a unit converter for Android + * Copyright (c) 2023 Elshan Agaev + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.sadellie.unitto.core.ui.common.datetimepicker + +import android.text.format.DateFormat +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.IntrinsicSize +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.outlined.Keyboard +import androidx.compose.material.icons.outlined.Schedule +import androidx.compose.material3.AlertDialog +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton +import androidx.compose.material3.TimeInput +import androidx.compose.material3.TimePicker +import androidx.compose.material3.rememberTimePickerState +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalConfiguration +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.semantics.isTraversalGroup +import androidx.compose.ui.semantics.semantics +import androidx.compose.ui.unit.dp +import androidx.compose.ui.window.DialogProperties +import androidx.compose.ui.zIndex +import com.sadellie.unitto.core.base.R + +// https://cs.android.com/androidx/platform/tools/dokka-devsite-plugin/+/master:testData/compose/samples/material3/samples/TimePickerSamples.kt +@Composable +fun TimePickerDialog( + hour: Int, + minute: Int, + onCancel: () -> Unit, + onConfirm: (hour: Int, minute: Int) -> Unit, + confirmLabel: String = stringResource(R.string.ok_label), +) { + val pickerState = rememberTimePickerState( + initialHour = hour, + initialMinute = minute, + is24Hour = DateFormat.is24HourFormat(LocalContext.current) + ) + val configuration = LocalConfiguration.current + var showingPicker by rememberSaveable { mutableStateOf(true) } + + AlertDialog( + onDismissRequest = onCancel, + properties = DialogProperties( + usePlatformDefaultWidth = false + ), + ) { + Surface( + shape = MaterialTheme.shapes.extraLarge, + tonalElevation = 6.dp, + modifier = Modifier + .width(IntrinsicSize.Min) + .height(IntrinsicSize.Min) + .background( + shape = MaterialTheme.shapes.extraLarge, + color = MaterialTheme.colorScheme.surface + ), + ) { + if (configuration.screenHeightDp > 400) { + // Make this take the entire viewport. This will guarantee that Screen readers + // focus the toggle first. + Box( + Modifier + .fillMaxSize() + .semantics { + isTraversalGroup = true + } + ) { + IconButton( + modifier = Modifier + // This is a workaround so that the Icon comes up first + // in the talkback traversal order. So that users of a11y + // services can use the text input. When talkback traversal + // order is customizable we can remove this. + .size(64.dp, 72.dp) + .align(Alignment.BottomStart) + .zIndex(5f), + onClick = { showingPicker = !showingPicker }) { + val icon = if (showingPicker) { + Icons.Outlined.Keyboard + } else { + Icons.Outlined.Schedule + } + Icon( + imageVector = icon, + contentDescription = stringResource(R.string.select_time_label) + ) + } + } + } + Column( + modifier = Modifier.padding(24.dp), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Text( + modifier = Modifier + .fillMaxWidth() + .padding(bottom = 20.dp), + text = stringResource(R.string.select_time_label), + style = MaterialTheme.typography.labelMedium + ) + if (showingPicker && configuration.screenHeightDp > 400) { + TimePicker(state = pickerState) + } else { + TimeInput(state = pickerState) + } + Row( + modifier = Modifier + .height(40.dp) + .fillMaxWidth() + ) { + Spacer(modifier = Modifier.weight(1f)) + TextButton( + onClick = onCancel + ) { Text(stringResource(R.string.cancel_label)) } + TextButton( + onClick = { onConfirm(pickerState.hour, pickerState.minute) } + ) { Text(confirmLabel) } + } + } + } + } +} diff --git a/feature/datecalculator/src/main/java/com/sadellie/unitto/feature/datecalculator/components/DateTimeDialogs.kt b/feature/datecalculator/src/main/java/com/sadellie/unitto/feature/datecalculator/components/DateTimeDialogs.kt index 86358a67..2ba14efa 100644 --- a/feature/datecalculator/src/main/java/com/sadellie/unitto/feature/datecalculator/components/DateTimeDialogs.kt +++ b/feature/datecalculator/src/main/java/com/sadellie/unitto/feature/datecalculator/components/DateTimeDialogs.kt @@ -21,8 +21,8 @@ package com.sadellie.unitto.feature.datecalculator.components import androidx.compose.runtime.Composable import androidx.compose.ui.res.stringResource import com.sadellie.unitto.core.base.R -import com.sadellie.unitto.core.ui.common.DatePickerDialog -import com.sadellie.unitto.core.ui.common.TimePickerDialog +import com.sadellie.unitto.core.ui.common.datetimepicker.DatePickerDialog +import com.sadellie.unitto.core.ui.common.datetimepicker.TimePickerDialog import java.time.ZonedDateTime @Composable diff --git a/feature/timezone/src/main/java/com/sadellie/unitto/feature/timezone/TimeZoneScreen.kt b/feature/timezone/src/main/java/com/sadellie/unitto/feature/timezone/TimeZoneScreen.kt index 16450252..56b8a087 100644 --- a/feature/timezone/src/main/java/com/sadellie/unitto/feature/timezone/TimeZoneScreen.kt +++ b/feature/timezone/src/main/java/com/sadellie/unitto/feature/timezone/TimeZoneScreen.kt @@ -75,7 +75,7 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.sadellie.unitto.core.base.R import com.sadellie.unitto.core.ui.common.MenuButton import com.sadellie.unitto.core.ui.common.SettingsButton -import com.sadellie.unitto.core.ui.common.TimePickerDialog +import com.sadellie.unitto.core.ui.common.datetimepicker.TimePickerDialog import com.sadellie.unitto.core.ui.common.UnittoEmptyScreen import com.sadellie.unitto.core.ui.common.UnittoScreenWithTopBar import com.sadellie.unitto.data.model.timezone.FavoriteZone