Skip to content

Commit

Permalink
Aggregated stats: start of the week uses regional preferences (Androi…
Browse files Browse the repository at this point in the history
…d14+).

Implemented using Material3's DatePicker.

Fixes #1681.
  • Loading branch information
dennisguse committed Sep 8, 2024
1 parent 00258fd commit 5415476
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 79 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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<Pair<Long, Long>> 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<LocalDateTime, LocalDateTime> 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<LocalDateTime, LocalDateTime> a = to(dateRangePicker);
filterDialogListener.onFilterDone(filterItems, a.first, a.second);
});
builder.setNegativeButton(android.R.string.cancel, null);

return builder.create();
}

private static Pair<LocalDateTime, LocalDateTime> to(MaterialDatePicker<Pair<Long, Long>> dateRangePicker) {
Pair<Long, Long> 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);
Expand Down
54 changes: 7 additions & 47 deletions src/main/res/layout/fragment_filter_dialog.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
xmlns:app="http://schemas.android.com/apk/res-auto">

<androidx.constraintlayout.widget.ConstraintLayout
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="8dp">

<com.google.android.material.button.MaterialButtonToggleGroup
Expand All @@ -17,11 +17,7 @@
android:layout_height="wrap_content"
android:padding="8dp"
android:orientation="vertical"
app:singleSelection="false"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toTopOf="@id/filter_date_from" />
app:singleSelection="false" />

<com.google.android.material.textfield.TextInputLayout
android:id="@+id/filter_date_from"
Expand All @@ -30,11 +26,7 @@
android:hint="@string/generic_from"
android:imeOptions="actionNext"
android:importantForAutofill="no"
android:padding="8dp"
app:layout_constraintTop_toBottomOf="@id/filter_items"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toTopOf="@id/filter_date_picker_from">
android:padding="8dp">

<com.google.android.material.textfield.TextInputEditText
android:id="@+id/filter_date_edit_text_from"
Expand All @@ -49,31 +41,14 @@

</com.google.android.material.textfield.TextInputLayout>

<DatePicker
android:id="@+id/filter_date_picker_from"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
tools:visibility="visible"
android:paddingLeft="8dp"
android:paddingRight="8dp"
app:layout_constraintTop_toBottomOf="@id/filter_date_from"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toTopOf="@id/filter_date_to" />

<com.google.android.material.textfield.TextInputLayout
android:id="@+id/filter_date_to"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/generic_to"
android:imeOptions="actionNext"
android:importantForAutofill="no"
android:padding="8dp"
app:layout_constraintTop_toBottomOf="@id/filter_date_picker_from"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toTopOf="@id/filter_date_picker_to">
android:padding="8dp">

<com.google.android.material.textfield.TextInputEditText
android:id="@+id/filter_date_edit_text_to"
Expand All @@ -87,20 +62,5 @@
android:selectAllOnFocus="true" />

</com.google.android.material.textfield.TextInputLayout>

<DatePicker
android:id="@+id/filter_date_picker_to"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
tools:visibility="visible"
android:paddingLeft="8dp"
android:paddingRight="8dp"
app:layout_constraintTop_toBottomOf="@id/filter_date_to"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

</LinearLayout>
</ScrollView>

0 comments on commit 5415476

Please sign in to comment.