Compose DatePicker

This commit is contained in:
FooIbar committed 2023-11-27 22:12:01 +08:00
1 parent 85bb9b9f97
commit 2ed957b5f2
4 files changed
+88 -33

No files matched your search

+1
View File
@@ -268,6 +268,7 @@ dependencies {
implementation(libs.bundles.kotlinx.serialization)
implementation(libs.kotlinx.coroutines.android)
implementation(libs.kotlinx.datetime)
implementation(libs.jsoup)
debugImplementation(libs.chucker)
@@ -42,6 +42,7 @@ import androidx.compose.material.icons.filled.Translate
import androidx.compose.material.icons.outlined.Bookmarks
import androidx.compose.material3.DismissDirection
import androidx.compose.material3.DismissValue
import androidx.compose.material3.DisplayMode
import androidx.compose.material3.ElevatedCard
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
@@ -50,6 +51,7 @@ import androidx.compose.material3.LeadingIconTab
import androidx.compose.material3.ListItem
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.PrimaryTabRow
import androidx.compose.material3.SelectableDates
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.pulltorefresh.rememberPullToRefreshState
@@ -97,12 +99,6 @@ import androidx.paging.PagingSource
import androidx.paging.PagingState
import androidx.paging.cachedIn
import androidx.paging.compose.collectAsLazyPagingItems
import com.google.android.material.datepicker.CalendarConstraints
import com.google.android.material.datepicker.CalendarConstraints.DateValidator
import com.google.android.material.datepicker.CompositeDateValidator
import com.google.android.material.datepicker.DateValidatorPointBackward
import com.google.android.material.datepicker.DateValidatorPointForward
import com.google.android.material.datepicker.MaterialDatePicker
import com.hippo.ehviewer.EhDB
import com.hippo.ehviewer.R
import com.hippo.ehviewer.Settings
@@ -159,15 +155,18 @@ import eu.kanade.tachiyomi.util.lang.launchIO
import eu.kanade.tachiyomi.util.lang.withIOContext
import eu.kanade.tachiyomi.util.lang.withUIContext
import java.io.File
import java.time.Instant
import java.time.LocalDateTime
import java.time.ZoneId
import java.time.ZoneOffset
import java.time.format.DateTimeFormatter
import java.util.Locale
import kotlin.math.roundToInt
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.datetime.Clock
import kotlinx.datetime.DateTimeUnit
import kotlinx.datetime.Instant
import kotlinx.datetime.LocalDate
import kotlinx.datetime.TimeZone
import kotlinx.datetime.atStartOfDayIn
import kotlinx.datetime.minus
import kotlinx.datetime.toLocalDateTime
import kotlinx.datetime.todayIn
import moe.tarsin.coroutines.runSuspendCatching
import sh.calvin.reorderable.ReorderableItem
import sh.calvin.reorderable.rememberReorderableLazyColumnState
@@ -837,27 +836,28 @@ fun GalleryListScreen(lub: ListUrlBuilder, navigator: DestinationsNavigator) {
urlBuilder.setJumpTo(text)
data.refresh()
} else {
val local = LocalDateTime.of(2007, 3, 21, 0, 0)
val fromDate =
local.atZone(ZoneId.ofOffset("UTC", ZoneOffset.UTC)).toInstant().toEpochMilli()
val toDate = MaterialDatePicker.todayInUtcMilliseconds()
val listValidators = ArrayList<DateValidator>()
listValidators.add(DateValidatorPointForward.from(fromDate))
listValidators.add(DateValidatorPointBackward.before(toDate))
val constraintsBuilder = CalendarConstraints.Builder()
.setStart(fromDate)
.setEnd(toDate)
.setValidator(CompositeDateValidator.allOf(listValidators))
val datePicker = MaterialDatePicker.Builder.datePicker()
.setCalendarConstraints(constraintsBuilder.build())
.setTitleText(R.string.go_to)
.setSelection(toDate)
.build()
datePicker.show(activity.supportFragmentManager, "date-picker")
datePicker.addOnPositiveButtonClickListener { time ->
val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd", Locale.US).withZone(ZoneOffset.UTC)
val jumpTo = formatter.format(Instant.ofEpochMilli(time))
urlBuilder.mJumpTo = jumpTo
val initial = LocalDate(2007, 3, 21)
val yesterday = Clock.System.todayIn(TimeZone.UTC).minus(1, DateTimeUnit.DAY)
val initialMillis = initial.atStartOfDayIn(TimeZone.UTC).toEpochMilliseconds()
val yesterdayMillis = yesterday.atStartOfDayIn(TimeZone.UTC).toEpochMilliseconds()
val dateRange = initialMillis..yesterdayMillis
coroutineScope.launch {
// TODO: Enable picker mode
// https://issuetracker.google.com/issues/306193893
val dateMillis = dialogState.showDatePicker(
title = R.string.go_to,
yearRange = initial.year..yesterday.year,
initialDisplayMode = DisplayMode.Input,
selectableDates = object : SelectableDates {
override fun isSelectableDate(utcTimeMillis: Long): Boolean {
return utcTimeMillis in dateRange
}
},
showModeToggle = false,
)
urlBuilder.mJumpTo = dateMillis?.let {
Instant.fromEpochMilliseconds(it).toLocalDateTime(TimeZone.UTC).date.toString()
}
data.refresh()
}
}
@@ -4,6 +4,7 @@ import androidx.annotation.StringRes
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.defaultMinSize
@@ -22,6 +23,10 @@ import androidx.compose.material3.AlertDialog
import androidx.compose.material3.AlertDialogDefaults
import androidx.compose.material3.BasicAlertDialog
import androidx.compose.material3.Checkbox
import androidx.compose.material3.DatePicker
import androidx.compose.material3.DatePickerDefaults
import androidx.compose.material3.DatePickerDialog
import androidx.compose.material3.DisplayMode
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.ListItem
@@ -29,12 +34,14 @@ import androidx.compose.material3.LocalContentColor
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.RadioButton
import androidx.compose.material3.SelectableDates
import androidx.compose.material3.ShapeDefaults
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.TextField
import androidx.compose.material3.TextFieldDefaults
import androidx.compose.material3.rememberDatePickerState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.compositionLocalOf
@@ -270,6 +277,50 @@ class DialogState {
}
}
suspend fun showDatePicker(
@StringRes title: Int,
initialSelectedDateMillis: Long? = null,
initialDisplayedMonthMillis: Long? = initialSelectedDateMillis,
yearRange: IntRange = DatePickerDefaults.YearRange,
initialDisplayMode: DisplayMode = DisplayMode.Picker,
selectableDates: SelectableDates = DatePickerDefaults.AllDates,
showModeToggle: Boolean = true,
): Long? {
return dialog { cont ->
val state = rememberDatePickerState(
initialSelectedDateMillis,
initialDisplayedMonthMillis,
yearRange,
initialDisplayMode,
selectableDates,
)
DatePickerDialog(
onDismissRequest = { cont.cancel() },
confirmButton = {
TextButton(onClick = { cont.resume(state.selectedDateMillis) }) {
Text(text = stringResource(id = android.R.string.ok))
}
},
dismissButton = {
TextButton(onClick = { cont.cancel() }) {
Text(text = stringResource(id = android.R.string.cancel))
}
},
) {
DatePicker(
state = state,
title = {
Text(
text = stringResource(id = title),
modifier = Modifier.padding(DatePickerTitlePadding),
)
},
showModeToggle = showModeToggle,
)
}
}
}
suspend fun <R> showNoButton(respectDefaultWidth: Boolean = true, block: @Composable DismissDialogScope<R>.() -> Unit): R {
return dialog { cont ->
val impl = remember(cont) {
@@ -483,5 +534,6 @@ class DialogState {
}
private val IconWithTextCorner = RoundedCornerShape(8.dp)
private val DatePickerTitlePadding = PaddingValues(start = 24.dp, end = 12.dp, top = 16.dp)
val LocalDialogState = compositionLocalOf<DialogState> { error("CompositionLocal LocalDialogState not present!") }
+2
View File
@@ -29,6 +29,7 @@ google-accompanist = "0.32.0"
google-android-material = "1.12.0-alpha01"
kotlin = "2.0.0-Beta1"
kotlinx-coroutines = "1.7.3"
kotlinx-datetime = "0.4.1"
kotlinx-serialization = "1.6.1"
ksp = "2.0.0-Beta1-1.0.14"
ktlint = "1.0.1"
@@ -105,6 +106,7 @@ insetter = "dev.chrisbanes.insetter:insetter:0.6.1"
jsoup = "org.jsoup:jsoup:1.17.1"
kotlinx-coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "kotlinx-coroutines" }
kotlinx-datetime = { module = "org.jetbrains.kotlinx:kotlinx-datetime", version.ref = "kotlinx-datetime" }
kotlinx-serialization-cbor = { module = "org.jetbrains.kotlinx:kotlinx-serialization-cbor", version.ref = "kotlinx-serialization" }
kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinx-serialization" }
kotlinx-serialization-json-okio = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json-okio", version.ref = "kotlinx-serialization" }