Skip to content

Export QSOs: date-range filter uses a Material date picker (typing still works) - #627

Merged
patrickrb merged 2 commits into
devfrom
optio/task-ff6d8752-c276-4e54-8b0e-237c3639af6e
Jul 22, 2026
Merged

Export QSOs: date-range filter uses a Material date picker (typing still works)#627
patrickrb merged 2 commits into
devfrom
optio/task-ff6d8752-c276-4e54-8b0e-237c3639af6e

Conversation

@patrickrb

Copy link
Copy Markdown
Owner

Summary

The Export QSOs sheet's date-range filter ("From" / "To") was two plain numeric EditText fields where the user had to hand-type a date as YYYYMMDD — no calendar, no validation. This adds a Material date picker behind a trailing calendar icon on each field while keeping the field fully editable by keyboard, so both input methods stay in sync and both emit the exact YYYYMMDD string the query layer expects.

What changed

  • dialog_export_log.xml — each date field gets a trailing drawableEnd calendar icon (ic_calendar_today.xml, new vector), maxLength=8, updated hint (YYYYMMDD) and label copy (From (optional) / To (optional)), plus a content description. The fields stay editable (not focusable=false).
  • ExportLogSheet.java
    • Tapping the calendar icon opens a MaterialDatePicker (shown via the hosting FragmentActivity's FragmentManager). A valid YYYYMMDD already in the field is preselected; otherwise today.
    • Selecting a date fills the field as YYYYMMDD. Typed entry still works; a field can be cleared back to empty (empty = no bound, unchanged behavior).
    • On Share and Save to Downloads, a non-empty field that is not a strict YYYYMMDD calendar date is rejected up front with ToastMessage.show(...) instead of running a broken query.
    • The value handed to ShareLogs.doShareLogs(...) / downQSLTableToFile(...) remains a YYYYMMDD string (or null when empty) — the ShareLogs date contract is untouched.

Testable logic

Per the repo's testing rule, the parse/validate/format decisions are extracted to package-private static helpers on ExportLogSheet (isValidOptionalDate, parseYyyyMmddUtc, formatYyyyMmddUtc) so the UI wrapper stays thin. All conversions are UTC to match MaterialDatePicker.todayInUtcMilliseconds(). Validation is strict (real calendar dates only — rejects Feb 30, month 13, wrong length, non-numeric, and year-0 via a format round-trip).

Tests

New ExportLogSheetDateTest (14 cases, pure JVM, no Robolectric needed) covering empty/null = valid, well-formed dates, whitespace tolerance, wrong length, non-numeric, impossible month/day, leap-day correctness, year-zero rejection, UTC-midnight parsing, formatting, and round-tripping.

./gradlew :app:testDebugUnitTest --tests com.k1af.ft8af.ui.ExportLogSheetDateTest
BUILD SUCCESSFUL — 14 tests, 0 failures

Acceptance criteria

  • Tapping the calendar affordance opens a Material date picker; picking a date populates the field as YYYYMMDD.
  • The user can still type a date manually into either field.
  • Picker and typed value stay consistent; a previously entered valid date is preselected when the picker opens.
  • Empty fields still export as "no bound".
  • A field can be cleared back to empty.
  • Invalid typed dates are rejected with a user-visible message; valid YYYYMMDD still filters via q.qso_date >= ?/<= ?.
  • Export (Share and Save) returns the same record set for equivalent ranges — the value reaching ShareLogs is unchanged in format.

Notes / assumptions

  • Change is confined to dialog_export_log.xml, ExportLogSheet.java, the new icon drawable, and the new test. ShareLogs is untouched.
  • Clearing after a pick is done via the still-editable keyboard field (no separate clear button added), which satisfies "provide a way to clear."
  • "End date not selectable before start date" was listed as a nice-to-have and is not implemented, to keep the change focused.

🤖 Generated with Claude Code

The From/To date-range fields in the Export QSOs sheet were plain numeric
EditTexts requiring a hand-typed YYYYMMDD value with no calendar UI and no
validation. This adds a MaterialDatePicker behind a trailing calendar icon on
each field while keeping the field fully editable by keyboard.

- Tapping the calendar icon opens a Material date picker; a valid YYYYMMDD
  already in the field is preselected, otherwise today.
- Selecting a date fills the field as YYYYMMDD; typed entry still works and a
  field can be cleared back to empty (empty = no bound, unchanged).
- On Share / Save, a non-empty field that is not a strict YYYYMMDD date is
  rejected with a ToastMessage instead of running a broken query.
- The value handed to ShareLogs remains a YYYYMMDD string (or null), so the
  query-layer date contract is unchanged.

Date parse/validate/format logic is extracted to package-private static
helpers on ExportLogSheet and covered by ExportLogSheetDateTest.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request updates the Android Export QSOs dialog to support selecting an optional date range via a Material date picker while keeping the existing typed YYYYMMDD workflow (and the downstream ShareLogs date-string contract) intact.

Changes:

  • Added a calendar affordance to the “From” / “To” date fields and wired it to a MaterialDatePicker with UTC-based parse/format helpers.
  • Added strict upfront validation for non-empty date inputs before running Share/Save exports.
  • Added pure-JVM unit tests covering date validation/parsing/formatting behaviors and edge cases.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
ft8af/app/src/main/java/com/k1af/ft8af/ui/ExportLogSheet.java Adds date-picker wiring, strict YYYYMMDD validation, and UTC parse/format helpers used by both picker and typed input paths.
ft8af/app/src/main/res/layout/dialog_export_log.xml Updates the export dialog date inputs with trailing calendar icon, hint/copy adjustments, and input constraints (maxLength=8).
ft8af/app/src/main/res/drawable/ic_calendar_today.xml Introduces a calendar vector drawable used as the date-field trailing icon.
ft8af/app/src/test/java/com/k1af/ft8af/ui/ExportLogSheetDateTest.java Adds JVM unit tests for the new date helper methods (validation, parsing, formatting, round-trip).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread ft8af/app/src/main/java/com/k1af/ft8af/ui/ExportLogSheet.java
Address Copilot review: the trailing calendar icon is a touch-only hit
target on the EditText's compound drawable, so TalkBack users could not
activate the picker. Register a ViewCompat custom accessibility action
("Open calendar date picker") on each field so the picker path is
operable via accessibility services, not just touch.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@patrickrb
patrickrb merged commit 2502443 into dev Jul 22, 2026
15 checks passed
@patrickrb
patrickrb deleted the optio/task-ff6d8752-c276-4e54-8b0e-237c3639af6e branch July 22, 2026 22:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants