Add buttons to date picker bottom sheet

pull/3432/head
Alex Baker 9 months ago
parent de42915ced
commit c78ec022a5

@ -0,0 +1,107 @@
package org.tasks.compose.pickers
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.statusBarsPadding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.DatePicker
import androidx.compose.material3.DatePickerDefaults
import androidx.compose.material3.DatePickerState
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.rememberModalBottomSheetState
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import org.tasks.R
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun DatePickerBottomSheet(
showButtons: Boolean,
dismiss: () -> Unit,
accept: () -> Unit,
dateShortcuts: @Composable ColumnScope.() -> Unit,
timeShortcuts: @Composable ColumnScope.() -> Unit,
state: DatePickerState,
) {
ModalBottomSheet(
modifier = Modifier.statusBarsPadding(),
sheetState = rememberModalBottomSheetState(
skipPartiallyExpanded = true,
),
onDismissRequest = { dismiss() },
containerColor = MaterialTheme.colorScheme.surface,
) {
Box(
modifier = Modifier.fillMaxWidth(),
) {
Column(
modifier = Modifier
.verticalScroll(rememberScrollState()),
) {
DatePicker(
state = state,
showModeToggle = false,
title = {},
colors = DatePickerDefaults.colors(
containerColor = MaterialTheme.colorScheme.surface,
),
headline = {
DatePickerShortcuts(
dateShortcuts = dateShortcuts,
timeShortcuts = timeShortcuts,
)
},
)
if (showButtons) {
Spacer(modifier = Modifier.height(56.dp))
}
}
if (showButtons) {
Surface(
modifier = Modifier
.align(Alignment.BottomCenter)
.fillMaxWidth(),
shadowElevation = 8.dp,
color = MaterialTheme.colorScheme.surface,
) {
Row(
modifier = Modifier
.height(56.dp)
.padding(horizontal = 24.dp, vertical = 4.dp),
horizontalArrangement = Arrangement.End,
verticalAlignment = Alignment.CenterVertically,
) {
TextButton(
onClick = { dismiss() }
) {
Text(stringResource(R.string.cancel))
}
Spacer(modifier = Modifier.width(8.dp))
TextButton(
onClick = { accept() }
) {
Text(stringResource(R.string.ok))
}
}
}
}
}
}
}

@ -16,6 +16,9 @@ abstract class BaseDateTimePicker : DialogFragment() {
}
protected var onDismissHandler: OnDismissHandler? = null
protected val autoclose by lazy {
arguments?.getBoolean(EXTRA_AUTO_CLOSE) ?: false
}
override fun onAttach(activity: Activity) {
super.onAttach(activity)
@ -33,8 +36,6 @@ abstract class BaseDateTimePicker : DialogFragment() {
override fun onCancel(dialog: DialogInterface) = sendSelected()
protected fun closeAutomatically(): Boolean = arguments?.getBoolean(EXTRA_AUTO_CLOSE) ?: false
protected abstract fun sendSelected()
companion object {

@ -6,16 +6,8 @@ import android.content.Intent
import android.os.Bundle
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.DatePicker
import androidx.compose.material3.DatePickerDefaults
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.rememberDatePickerState
import androidx.compose.material3.rememberModalBottomSheetState
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
@ -24,7 +16,6 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.fragment.app.Fragment
import androidx.fragment.compose.content
import androidx.lifecycle.lifecycleScope
@ -32,7 +23,7 @@ import com.todoroo.astrid.dao.TaskDao
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.NonCancellable
import kotlinx.coroutines.launch
import org.tasks.compose.pickers.DatePickerShortcuts
import org.tasks.compose.pickers.DatePickerBottomSheet
import org.tasks.compose.pickers.DueDateShortcuts
import org.tasks.compose.pickers.TimePickerDialog
import org.tasks.compose.pickers.TimeShortcuts
@ -126,31 +117,41 @@ class DateTimePicker : BaseDateTimePicker() {
savedInstanceState: Bundle?,
) = content {
TasksTheme(theme = theme.themeBase.index) {
val sheetState = rememberModalBottomSheetState(
skipPartiallyExpanded = true,
)
ModalBottomSheet(
sheetState = sheetState,
onDismissRequest = {
onDismissHandler?.onDismiss() ?: dismiss()
},
containerColor = MaterialTheme.colorScheme.surface,
) {
val state = rememberDatePickerState()
Column(
modifier = Modifier.verticalScroll(rememberScrollState())
) {
DatePicker(
DatePickerBottomSheet(
state = state,
showModeToggle = false,
title = {},
headline = {
DatePickerShortcuts(
showButtons = !autoclose,
dismiss = { onDismissHandler?.onDismiss() ?: dismiss() },
accept = { sendSelected() },
dateShortcuts = {
DueDateShortcuts(
today = today.millis,
tomorrow = remember { today.plusDays(1).millis },
nextWeek = remember { today.plusDays(7).millis },
selected = selectedDay,
showNoDate = remember {
!requireArguments().getBoolean(
EXTRA_HIDE_NO_DATE,
false
)
},
selectedDay = { returnDate(it.startOfDay()) },
clearDate = { returnDate(day = 0, time = 0) },
)
},
timeShortcuts = {
var showTimePicker by rememberSaveable { mutableStateOf(false) }
var showTimePicker by rememberSaveable {
mutableStateOf(
false
)
}
if (showTimePicker) {
val time = if (selectedTime == MULTIPLE_TIMES
|| !Task.hasDueTime(today.withMillisOfDay(selectedTime).millis)
|| !Task.hasDueTime(
today.withMillisOfDay(
selectedTime
).millis
)
) {
today.noon().millisOfDay
} else {
@ -175,30 +176,8 @@ class DateTimePicker : BaseDateTimePicker() {
pickTime = { showTimePicker = true },
clearTime = { returnDate(time = 0) },
)
},
dateShortcuts = {
DueDateShortcuts(
today = today.millis,
tomorrow = remember { today.plusDays(1).millis },
nextWeek = remember { today.plusDays(7).millis },
selected = selectedDay,
showNoDate = remember {
!requireArguments().getBoolean(
EXTRA_HIDE_NO_DATE,
false
)
},
selectedDay = { returnDate(it.startOfDay()) },
clearDate = { returnDate(day = 0, time = 0) },
)
},
)
},
colors = DatePickerDefaults.colors(
containerColor = MaterialTheme.colorScheme.surface,
),
)
}
)
LaunchedEffect(selectedDay) {
if (selectedDay > 0) {
state.selectedDateMillis = selectedDay + (DateTime(selectedDay).offset)
@ -216,7 +195,6 @@ class DateTimePicker : BaseDateTimePicker() {
}
}
}
}
private fun returnSelectedTime(millisOfDay: Int) {
val day = when {
@ -231,7 +209,7 @@ class DateTimePicker : BaseDateTimePicker() {
private fun returnDate(day: Long = selectedDay, time: Int = selectedTime) {
selectedDay = day
selectedTime = time
if (closeAutomatically()) {
if (autoclose) {
sendSelected()
}
}

@ -6,16 +6,8 @@ import android.content.Intent
import android.os.Bundle
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.DatePicker
import androidx.compose.material3.DatePickerDefaults
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.rememberDatePickerState
import androidx.compose.material3.rememberModalBottomSheetState
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
@ -24,12 +16,11 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.fragment.app.Fragment
import androidx.fragment.compose.content
import com.todoroo.astrid.dao.TaskDao
import dagger.hilt.android.AndroidEntryPoint
import org.tasks.compose.pickers.DatePickerShortcuts
import org.tasks.compose.pickers.DatePickerBottomSheet
import org.tasks.compose.pickers.StartDateShortcuts
import org.tasks.compose.pickers.TimePickerDialog
import org.tasks.compose.pickers.TimeShortcuts
@ -93,26 +84,20 @@ class StartDatePicker : BaseDateTimePicker() {
savedInstanceState: Bundle?
) = content {
TasksTheme(theme = theme.themeBase.index) {
val sheetState = rememberModalBottomSheetState(
skipPartiallyExpanded = true,
)
ModalBottomSheet(
sheetState = sheetState,
onDismissRequest = {
onDismissHandler?.onDismiss() ?: dismiss()
},
containerColor = MaterialTheme.colorScheme.surface,
) {
val state = rememberDatePickerState()
Column(
modifier = Modifier.verticalScroll(rememberScrollState()),
) {
DatePicker(
DatePickerBottomSheet(
state = state,
showModeToggle = false,
title = {},
headline = {
DatePickerShortcuts(
showButtons = !autoclose,
dismiss = { onDismissHandler?.onDismiss() ?: dismiss() },
accept = { sendSelected() },
dateShortcuts = {
StartDateShortcuts(
selected = selectedDay,
selectedDay = { returnDate(it) },
selectedDayTime = { day, time -> returnDate(day, time) },
clearDate = { returnDate(day = 0, time = 0) },
)
},
timeShortcuts = {
var showTimePicker by rememberSaveable { mutableStateOf(false) }
if (showTimePicker) {
@ -151,22 +136,8 @@ class StartDatePicker : BaseDateTimePicker() {
)
},
)
},
dateShortcuts = {
StartDateShortcuts(
selected = selectedDay,
selectedDay = { returnDate(it) },
selectedDayTime = { day, time -> returnDate(day, time) },
clearDate = { returnDate(day = 0, time = 0) },
)
},
)
},
colors = DatePickerDefaults.colors(
containerColor = MaterialTheme.colorScheme.surface,
),
}
)
LaunchedEffect(selectedDay) {
if (selectedDay > 0) {
state.selectedDateMillis = selectedDay + (DateTime(selectedDay).offset)
@ -184,8 +155,6 @@ class StartDatePicker : BaseDateTimePicker() {
}
}
}
}
}
private fun returnSelectedTime(millisOfDay: Int) {
val day = when {
@ -200,7 +169,7 @@ class StartDatePicker : BaseDateTimePicker() {
private fun returnDate(day: Long = selectedDay, time: Int = selectedTime) {
selectedDay = day
selectedTime = time
if (closeAutomatically()) {
if (autoclose) {
sendSelected()
}
}

Loading…
Cancel
Save