From 245ca2a5d159e3dab74c5aa633d906872065ed0b Mon Sep 17 00:00:00 2001 From: adrcotfas Date: Sun, 19 Mar 2023 10:22:30 +0200 Subject: [PATCH] bugfix: date picker misbehavior --- app/build.gradle | 4 +- .../all_sessions/AddEditEntryDialog.kt | 30 +++++++-- .../apps/adrcotfas/goodtime/util/TimeUtils.kt | 63 ++++++++++++------- 3 files changed, 67 insertions(+), 30 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index b15452a0..0e0e4041 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -14,8 +14,8 @@ android { applicationId "com.apps.adrcotfas.goodtime" minSdkVersion 23 targetSdkVersion 33 - versionCode 149 - versionName "2.5.6" + versionCode 151 + versionName "2.5.8" resConfigs "ar-rSA", "bn-rBD", "bs-rBA", diff --git a/app/src/main/java/com/apps/adrcotfas/goodtime/statistics/all_sessions/AddEditEntryDialog.kt b/app/src/main/java/com/apps/adrcotfas/goodtime/statistics/all_sessions/AddEditEntryDialog.kt index bd6cf535..65fa35ed 100644 --- a/app/src/main/java/com/apps/adrcotfas/goodtime/statistics/all_sessions/AddEditEntryDialog.kt +++ b/app/src/main/java/com/apps/adrcotfas/goodtime/statistics/all_sessions/AddEditEntryDialog.kt @@ -27,6 +27,7 @@ import android.view.View import com.apps.adrcotfas.goodtime.statistics.main.SelectLabelDialog import com.apps.adrcotfas.goodtime.statistics.main.StatisticsActivity import android.widget.Toast +import androidx.core.content.res.ResourcesCompat import androidx.fragment.app.viewModels import com.apps.adrcotfas.goodtime.database.Label import com.apps.adrcotfas.goodtime.database.Session @@ -37,6 +38,7 @@ import com.apps.adrcotfas.goodtime.util.* import dagger.hilt.android.AndroidEntryPoint import java.lang.Integer.min import java.time.LocalTime +import java.util.* @AndroidEntryPoint class AddEditEntryDialog : BottomSheetDialogFragment(), OnLabelSelectedListener { @@ -115,14 +117,20 @@ class AddEditEntryDialog : BottomSheetDialogFragment(), OnLabelSelectedListener if (label != null && label != getString(R.string.label_unlabeled)) { binding.labelChip.text = label labelsViewModel.getColorOfLabel(label) - .observe(viewLifecycleOwner, { color: Int? -> + .observe(viewLifecycleOwner) { color: Int? -> binding.labelChip.chipBackgroundColor = ColorStateList.valueOf( ThemeHelper.getColor( requireContext(), color!! ) ) - }) - binding.labelDrawable.setImageDrawable(resources.getDrawable(R.drawable.ic_label)) + } + binding.labelDrawable.setImageDrawable( + ResourcesCompat.getDrawable( + resources, + R.drawable.ic_label, + null + ) + ) } else { binding.labelChip.text = resources.getString(R.string.label_add) binding.labelChip.chipBackgroundColor = ColorStateList.valueOf( @@ -130,7 +138,13 @@ class AddEditEntryDialog : BottomSheetDialogFragment(), OnLabelSelectedListener requireContext(), ThemeHelper.COLOR_INDEX_UNLABELED ) ) - binding.labelDrawable.setImageDrawable(resources.getDrawable(R.drawable.ic_label_off)) + binding.labelDrawable.setImageDrawable( + ResourcesCompat.getDrawable( + resources, + R.drawable.ic_label_off, + null + ) + ) } } @@ -161,9 +175,13 @@ class AddEditEntryDialog : BottomSheetDialogFragment(), OnLabelSelectedListener } binding.editDate.setOnClickListener { - val picker = DatePickerDialogHelper.buildDatePicker(timestamp) + val picker = + DatePickerDialogHelper.buildDatePicker( + timestamp.toUtcMillis() + ) picker.addOnPositiveButtonClickListener { - val newLocalDate = it.toLocalDate() + val newLocalDate = + it.toZoneLocalDateTime() viewModel.session.timestamp = Pair(newLocalDate, localTime).toLocalDateTime().millis binding.editDate.text = TimeUtils.formatDateLong(newLocalDate) //TODO: extract as extension function diff --git a/app/src/main/java/com/apps/adrcotfas/goodtime/util/TimeUtils.kt b/app/src/main/java/com/apps/adrcotfas/goodtime/util/TimeUtils.kt index 348966bc..8cca3f48 100644 --- a/app/src/main/java/com/apps/adrcotfas/goodtime/util/TimeUtils.kt +++ b/app/src/main/java/com/apps/adrcotfas/goodtime/util/TimeUtils.kt @@ -44,28 +44,28 @@ class TimeUtils { return time.format(DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT)) } - fun firstDayOfCurrentWeekMillis() : Long { + fun firstDayOfCurrentWeekMillis(): Long { return LocalDate.now() - .atStartOfDay() - .with(TemporalAdjusters.previousOrSame(firstDayOfWeek())) - .atZone(ZoneId.systemDefault()) - .toInstant().toEpochMilli() + .atStartOfDay() + .with(TemporalAdjusters.previousOrSame(firstDayOfWeek())) + .atZone(ZoneId.systemDefault()) + .toInstant().toEpochMilli() } fun firstDayOfLastWeekMillis(): Long { return LocalDate.now() - .minus(1, ChronoUnit.WEEKS) - .atStartOfDay() - .with(TemporalAdjusters.previousOrSame(firstDayOfWeek())) - .atZone(ZoneId.systemDefault()) - .toInstant().toEpochMilli() + .minus(1, ChronoUnit.WEEKS) + .atStartOfDay() + .with(TemporalAdjusters.previousOrSame(firstDayOfWeek())) + .atZone(ZoneId.systemDefault()) + .toInstant().toEpochMilli() } fun nowMillis(): Long { return LocalDateTime.now() - .atZone(ZoneId.systemDefault()) - .toInstant() - .toEpochMilli() + .atZone(ZoneId.systemDefault()) + .toInstant() + .toEpochMilli() } } } @@ -80,31 +80,50 @@ fun secondsOfDayToTimerFormat(seconds: Int, is24HourFormat: Boolean = true): Str ) } -fun Long.toLocalDateTime() : LocalDateTime { +fun Long.toLocalDateTime(): LocalDateTime { return Instant.ofEpochMilli(this).atZone(ZoneId.systemDefault()).toLocalDateTime() } -fun Long.toLocalDate() : LocalDate { +fun Long.toLocalDate(): LocalDate { return Instant.ofEpochMilli(this).atZone(ZoneId.systemDefault()).toLocalDate() } -fun Long.toLocalTime() : LocalTime { +// The following two functions are required to convert from Zone date time to UTC date time and back +// MaterialDatePicker uses UTC time +fun Long.toUtcLocalDateTime(): LocalDateTime = + Instant.ofEpochMilli(this).atZone(ZoneId.ofOffset("UTC", ZoneOffset.UTC)).toLocalDateTime() + +fun Long.toZoneLocalDateTime(): LocalDate = + toUtcLocalDateTime().atZone(ZoneId.systemDefault()).toLocalDate() + +fun Long.toLocalTime(): LocalTime { return Instant.ofEpochMilli(this).atZone(ZoneId.systemDefault()).toLocalTime() } -fun Pair.toLocalDateTime() : LocalDateTime { +fun Long.toUtcMillis() = toLocalDateTime().atZone(ZoneId.ofOffset("UTC", ZoneOffset.UTC)) + .toInstant().toEpochMilli() + +fun Pair.toLocalDateTime(): LocalDateTime { return LocalDateTime.of(this.first, this.second) } val LocalDateTime.millis get() = this.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli() -fun LocalTime.toFormattedTime(): String = this.format(DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT)) -fun LocalDate.toFormattedDate(): String = this.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM)) -fun LocalDateTime.toFormattedDateTime(): String = this.format(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM)) +fun LocalTime.toFormattedTime(): String = + this.format(DateTimeFormatter.ofLocalizedTime(FormatStyle.SHORT)) + +fun LocalDate.toFormattedDate(): String = + this.format(DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM)) + +fun LocalDateTime.toFormattedDateTime(): String = + this.format(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM)) + +fun startOfTodayMillis() = + LocalDate.now().atStartOfDay(ZoneId.systemDefault()).toInstant().toEpochMilli() -fun startOfTodayMillis() = LocalDate.now().atStartOfDay(ZoneId.systemDefault()).toInstant().toEpochMilli() -fun startOfTomorrowMillis() = LocalDate.now().plusDays(1).atStartOfDay(ZoneId.systemDefault()).toInstant().toEpochMilli() +fun startOfTomorrowMillis() = + LocalDate.now().plusDays(1).atStartOfDay(ZoneId.systemDefault()).toInstant().toEpochMilli() fun firstDayOfWeek(): DayOfWeek = WeekFields.of(Locale.getDefault()).firstDayOfWeek