From 7925455011eb5cd924d418526ec12a9fbc1a7bc0 Mon Sep 17 00:00:00 2001 From: Dennis Guse Date: Sun, 8 Sep 2024 09:38:32 +0200 Subject: [PATCH] Aggregated stats: start of the week uses regional preferences (Android14+). Implemented using Material3's DatePicker. Fixes #1681. --- .../FilterDialogFragment.java | 73 +++++++++++-------- .../res/layout/fragment_filter_dialog.xml | 54 ++------------ 2 files changed, 48 insertions(+), 79 deletions(-) diff --git a/src/main/java/de/dennisguse/opentracks/ui/aggregatedStatistics/FilterDialogFragment.java b/src/main/java/de/dennisguse/opentracks/ui/aggregatedStatistics/FilterDialogFragment.java index 75dd378d45..5241e7c971 100644 --- a/src/main/java/de/dennisguse/opentracks/ui/aggregatedStatistics/FilterDialogFragment.java +++ b/src/main/java/de/dennisguse/opentracks/ui/aggregatedStatistics/FilterDialogFragment.java @@ -10,15 +10,18 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.app.AlertDialog; +import androidx.core.util.Pair; import androidx.fragment.app.DialogFragment; import androidx.fragment.app.FragmentManager; +import com.google.android.material.datepicker.MaterialDatePicker; + +import java.time.Instant; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.ZoneOffset; -import java.time.temporal.WeekFields; import java.util.ArrayList; -import java.util.Locale; +import java.util.TimeZone; import de.dennisguse.opentracks.R; import de.dennisguse.opentracks.databinding.FragmentFilterDialogBinding; @@ -65,49 +68,55 @@ public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) { layout.filterItems.addView(view.getRoot()); } - LocalDateTime firstDayThisWeek = LocalDate.now().with(WeekFields.of(Locale.getDefault()).getFirstDayOfWeek()).atStartOfDay(); - layout.filterDateEditTextFrom.setText(StringUtils.formatLocalDateTime(firstDayThisWeek)); - layout.filterDatePickerFrom.init(firstDayThisWeek.getYear(), firstDayThisWeek.getMonthValue() - 1, firstDayThisWeek.getDayOfMonth(), (view, year, monthOfYear, dayOfMonth) -> { - LocalDateTime localDateTime = LocalDateTime.of(year, monthOfYear + 1, dayOfMonth, 0, 0, 0); - layout.filterDateEditTextFrom.setText(StringUtils.formatLocalDateTime(localDateTime)); - layout.filterDatePickerFrom.setVisibility(View.GONE); - layout.filterDatePickerTo.setMinDate(localDateTime.toInstant(ZoneOffset.ofTotalSeconds(0)).toEpochMilli()); - if (localDateTime.isAfter(LocalDateTime.of(layout.filterDatePickerTo.getYear(), layout.filterDatePickerTo.getMonth() + 1, layout.filterDatePickerTo.getDayOfMonth(), 23, 59, 59))) { - layout.filterDatePickerTo.updateDate(year, monthOfYear, dayOfMonth); - } - }); - LocalDateTime lastDayThisWeek = firstDayThisWeek.plusDays(6).withHour(23).withMinute(59).withSecond(59); - layout.filterDateEditTextTo.setText(StringUtils.formatLocalDateTime(lastDayThisWeek)); - layout.filterDatePickerTo.init(lastDayThisWeek.getYear(), lastDayThisWeek.getMonthValue() - 1, lastDayThisWeek.getDayOfMonth(), (view, year, monthOfYear, dayOfMonth) -> { - LocalDateTime localDateTime = LocalDateTime.of(year, monthOfYear + 1, dayOfMonth, 23, 59, 59); - layout.filterDateEditTextTo.setText(StringUtils.formatLocalDateTime(localDateTime)); - layout.filterDatePickerTo.setVisibility(View.GONE); - }); + // Interval is last 7 days. + LocalDateTime initialToDate = LocalDate.now().atStartOfDay(); + LocalDateTime initialFromDate = initialToDate.minusDays(6); - layout.filterDateEditTextFrom.setOnClickListener(v -> { - layout.filterDatePickerFrom.setVisibility(View.VISIBLE); - layout.filterDatePickerTo.setVisibility(View.GONE); - }); + MaterialDatePicker> dateRangePicker = MaterialDatePicker.Builder + .dateRangePicker() + .setSelection(new Pair<>( + initialFromDate.toInstant(ZoneOffset.UTC).toEpochMilli(), + initialToDate.toInstant(ZoneOffset.UTC).toEpochMilli()) + + ) + .build(); + + layout.filterDateEditTextFrom.setText(StringUtils.formatLocalDateTime(initialFromDate)); + layout.filterDateEditTextTo.setText(StringUtils.formatLocalDateTime(initialToDate)); - layout.filterDateEditTextTo.setOnClickListener(v -> { - layout.filterDatePickerFrom.setVisibility(View.GONE); - layout.filterDatePickerTo.setVisibility(View.VISIBLE); + dateRangePicker.addOnPositiveButtonClickListener(selection -> { + Pair javaxSelection = to(dateRangePicker); + + layout.filterDateEditTextFrom.setText(StringUtils.formatLocalDateTime(javaxSelection.first)); + layout.filterDateEditTextTo.setText(StringUtils.formatLocalDateTime(javaxSelection.second)); }); + View.OnClickListener openDatePicker = v -> dateRangePicker.show(getChildFragmentManager(), "DATE_PICKER"); + layout.filterDateEditTextFrom.setOnClickListener(openDatePicker); + layout.filterDateEditTextTo.setOnClickListener(openDatePicker); + AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); builder.setTitle(getString(R.string.generic_filter)); builder.setView(layout.getRoot()); - builder.setPositiveButton(android.R.string.ok, (dialog, which) -> filterDialogListener.onFilterDone( - filterItems, - LocalDateTime.of(layout.filterDatePickerFrom.getYear(), layout.filterDatePickerFrom.getMonth() + 1, layout.filterDatePickerFrom.getDayOfMonth(), 0, 0, 0), - LocalDateTime.of(layout.filterDatePickerTo.getYear(), layout.filterDatePickerTo.getMonth() + 1, layout.filterDatePickerTo.getDayOfMonth(), 23, 59, 59) - )); + builder.setPositiveButton(android.R.string.ok, (dialog, which) -> { + Pair a = to(dateRangePicker); + filterDialogListener.onFilterDone(filterItems, a.first, a.second); + }); builder.setNegativeButton(android.R.string.cancel, null); return builder.create(); } + private static Pair to(MaterialDatePicker> dateRangePicker) { + Pair selection = dateRangePicker.getSelection(); + + return new Pair<>( + LocalDateTime.ofInstant(Instant.ofEpochMilli(selection.first), TimeZone.getDefault().toZoneId()), + LocalDateTime.ofInstant(Instant.ofEpochMilli(selection.second), TimeZone.getDefault().toZoneId()) + ); + } + @Override public void onAttach(@NonNull Context context) { super.onAttach(context); diff --git a/src/main/res/layout/fragment_filter_dialog.xml b/src/main/res/layout/fragment_filter_dialog.xml index 8b2b715ba1..2668f71fda 100644 --- a/src/main/res/layout/fragment_filter_dialog.xml +++ b/src/main/res/layout/fragment_filter_dialog.xml @@ -3,12 +3,12 @@ + xmlns:app="http://schemas.android.com/apk/res-auto"> - + app:singleSelection="false" /> + android:padding="8dp"> - - + android:padding="8dp"> - - - - - + \ No newline at end of file