crossmate

A collaborative crossword app for iOS
Log | Files | Refs | LICENSE

commit b5b7b6e04ce569cdfd3bffb0b1b4038fa16c7be5
parent 8257d1666f32689c3273cf83c159a6ea4fa40b30
Author: Michael Camilleri <[email protected]>
Date:   Thu, 21 May 2026 12:47:00 +0900

Improve NYT date navigation

This commit adds a tappable month title that opens a compact wheel date picker
with Cancel and Done controls, allowing archive jumps without applying changes
until confirmed.

Co-Authored-By: Codex GPT 5.5 <[email protected]>

Diffstat:
MCrossmate/Views/NYTBrowseView.swift | 58+++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 57 insertions(+), 1 deletion(-)

diff --git a/Crossmate/Views/NYTBrowseView.swift b/Crossmate/Views/NYTBrowseView.swift @@ -10,6 +10,8 @@ struct NYTBrowseView: View { @State private var isLoading = false @State private var errorMessage: String? @State private var sessionExpired = false + @State private var showingMonthPicker = false + @State private var pickerDate: Date = NYTBrowseView.startOfCurrentMonth() private static let nytTimeZone = TimeZone(identifier: "America/New_York")! @@ -86,8 +88,22 @@ struct NYTBrowseView: View { Spacer() - Text(monthTitle) + Button { + pickerDate = selectedDate ?? displayedMonth + showingMonthPicker = true + } label: { + HStack(spacing: 4) { + Text(monthTitle) + Image(systemName: "chevron.down") + .font(.caption.weight(.semibold)) + } .font(.headline) + } + .buttonStyle(.plain) + .popover(isPresented: $showingMonthPicker) { + dateWheelPopover + .presentationCompactAdaptation(.popover) + } Spacer() @@ -159,6 +175,40 @@ struct NYTBrowseView: View { return "Start \(selectedDate.formatted(style))" } + private var dateWheelPopover: some View { + VStack(spacing: 14) { + HStack { + Button("Cancel", role: .cancel) { + showingMonthPicker = false + } + + Spacer() + + Button("Done") { + selectedDate = pickerDate + displayedMonth = startOfMonth(for: pickerDate) + showingMonthPicker = false + } + .buttonStyle(.borderedProminent) + } + + DatePicker( + "Puzzle Date", + selection: $pickerDate, + in: Self.minDate...Date(), + displayedComponents: .date + ) + .datePickerStyle(.wheel) + .labelsHidden() + .environment(\.calendar, Self.nytCalendar) + .environment(\.timeZone, Self.nytTimeZone) + .frame(width: 320, height: 160) + .clipped() + } + .padding(.horizontal) + .padding(.vertical, 8) + } + private func isSelected(_ date: Date) -> Bool { guard let selectedDate else { return false } return Self.nytCalendar.isDate(date, inSameDayAs: selectedDate) @@ -173,6 +223,12 @@ struct NYTBrowseView: View { } } + private func startOfMonth(for date: Date) -> Date { + let cal = Self.nytCalendar + let components = cal.dateComponents([.year, .month], from: date) + return cal.date(from: components) ?? date + } + private var monthTitle: String { let formatter = DateFormatter() formatter.calendar = Self.nytCalendar