Repository navigation
Conversation
In the calendar's Day and Week views Enter did nothing on a highlighted event, and inside a Year cell it did nothing either, while the content help bar advertised "enter open" the whole time (the generic rowContent binding, live in Mail and dead here). The only way to see an event's notes, location, link or guests was to open the edit form with `e`. Enter now opens a read-only detail card over the grid, the way Contacts opens a contact on Enter and leaves `e` for editing. The card is built from the selected Recording alone -- the grid read already carries Notes, Location, Link and Attendees -- so nothing is fetched. From the card `o` opens the link, `e` swaps in the edit form on the same event, esc/q closes it, and the arrows and page keys scroll the notes. The card is an inputCapturer, so it handles esc itself and the help bar shows its keys instead of the generic "enter open". Two safeguards on what the card shows and does: - `o` only hands an http/https link to the OS launcher. Event links are server data and the edit form accepts any URI with a host, so a shared event could carry a file:// path or an application scheme; those are shown on the card but not opened, and `o` is not offered for them. - The when-and-where line shows the reader's local clock, the same conversion Recording.Starts/Ends and the grid make, rather than labelling a converted time with the event's original zone. The calendar name is sanitized like every other view of server metadata. Year view keeps its two stages: Enter steps into a cell, and only once inside does it open the selected event. Fixes #418 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01C6Y2KeiHB6QNWmHdgqbzD1
…eek-view test - openableLink: require non-empty host and compare scheme case-insensitively, so hostless URIs (https:roadmap, https://) and uppercase schemes are handled. - content() rows: wrap long values (URL, attendee list) to available modal width so no row makes the modal wider than the terminal. - wrapText: hard-wrap tokens that exceed maxWidth so a long URL in notes cannot overflow the card viewport. - when() all-day: collapse same-day ends and subtract exclusive midnight boundary so Aug 21 00:00–23:59 and Aug 21 00:00–Aug 22 00:00 both show as a single day. - Add TestEnterOpensTheEventCardOnWeekView, TestAllDayEvent*, TestWrapText* and extend TestEventDetailOpensOnlyHostedWebLinks with new cases.
…l when() line - wrapText: use displayWidth/fitGraphemes instead of byte slicing so hard-wrap never splits inside a rune or emoji sequence, and wide characters (emoji, CJK) are measured in terminal cells rather than bytes. - content(): wrap the when() line to modalContentWidth so a long weekday+time range does not overflow the modal on narrow terminals. - Add TestWrapTextSplitsAtGraphemeBoundaries and TestEventCardWhenLineWrapsOnNarrowTerminal.
…rorView - calendar.go: only clear the detail card after confirming v.eventForm was created; if startEventForm finds no fileable calendars it returns an error notice without setting v.eventForm, so a failed edit transition now leaves the read-only card visible instead of leaving the user with nothing. - styles.go: use displayWidth instead of len() in errorView so the box width is measured in terminal cells, consistent with wrapText's new contract; a line of wide characters (emoji, CJK) no longer expands the error box past the terminal.
…apText - event_detail.go: show 'Repeats on a schedule' when Recurring is true but the kind is not a known preset, matching the form's own treatment of unknown schedules (event_form_test.go:742-744). - event_detail.go: use parsed.Hostname() instead of parsed.Host so that a port-only authority like 'https://:443' is correctly rejected. - styles.go: compute displayWidth(w) once per word before the hard-wrap loop and update it after each chunk, keeping the inner loop O(n) instead of O(n²).
…advance, linear wrapText - event_detail.go: switch to stacked label layout (label truncated to contentWidth, value indented by 2) when contentWidth <= labelWidth, so no row overflows the modal on very narrow terminals. - styles.go: when the leading grapheme of a word is wider than maxWidth, emit it as-is and advance past it (instead of breaking) so the suffix is still wrapped. - styles.go: subtract the emitted chunk width from wWidth instead of scanning the remaining suffix with displayWidth, keeping the hard-wrap loop strictly linear.
There was a problem hiding this comment.
🟡 Changes recommended
The card subtracts a day from inclusive all-day end dates, displaying shortened event ranges.
1 open issue
What changed in this PR
Adds read-only calendar event cards to the TUI, addressing Enter doing nothing on selected events in #418.
Changes:
- Opens event details in Day, Week, and Year cells, with scrolling, web links, and editing.
- Adds regression coverage and terminal-cell-aware wrapping.
- Updates calendar shortcut documentation.
[!TIP]
If you aren't ready for review, convert to a draft PR.
Click "Convert to draft" or rungh pr ready --undo.
Click "Ready for review" or rungh pr readyto reengage.
| File | Description |
|---|---|
| internal/tui/styles.go | Wraps text by terminal cells and grapheme boundaries. |
| internal/tui/event_detail.go | Implements the event detail card. |
| internal/tui/event_detail_test.go | Tests links, dates, wrapping, and layouts. |
| internal/tui/event_detail_review_test.go | Covers preferences, scrolling, sanitization, and edit freshness. |
| internal/tui/calendar.go | Integrates card navigation and lifecycle. |
| internal/tui/calendar_test.go | Tests card interactions and Year navigation. |
| internal/tui/calendar_enter_test.go | Verifies Enter displays event notes. |
| docs/tui.md | Documents cards and corrects calendar shortcuts. |
Review effort: Balanced
| if ends.Equal(time.Date(ends.Year(), ends.Month(), ends.Day(), 0, 0, 0, 0, ends.Location())) { | ||
| endDay = ends.AddDate(0, 0, -1) |
|
🤖 Fixed the inclusive all-day end-date review finding in Preserve inclusive all-day date ranges. Confirmed the contract against demo data rather than assuming an exclusive midnight boundary. An all-day event created for October 20 through 22 is returned by the SDK-backed Day read on October 22, not October 23, with Removed all-day date subtraction from the card. The grid had the same assumption, so it now includes the final day for all-day events while preserving exclusive midnight handling for timed events. Replaced incorrect exclusive-date test fixtures with exact inclusive-date assertions, including adjacent dates, longer ranges, UTC dates under a New York clock and both DST boundaries. Validation
Build, formatting, vet and lint pass. The full local suite still hits only the previously disclosed missing file(1) backend; the internal and TUI race suites pass with that single environment-dependent exclusion. All active CI checks pass on the new head, including full Tests and Race Detection. Independent review approves the fix. Recorded both real binaries against the same demo event. The corrected card shows October 20 through 22 and opens from the final day's grid. No edit was saved. |

🤖 Opened by an autonomous agent on behalf of its operator.
Enter now opens a read-only calendar event card instead of doing nothing.
Continues Albert Reig's event-card pull request. All six contributor commits retain their authorship. This replacement carries the remaining review fixes; the original stays open for a maintainer's decision.
Changes
Addresses Enter does nothing on a highlighted event. No SDK or dependency changes.
Validation
go test ./internal/tui -run '^TestCalendarEnterShowsEventNotes$' -count=1 -vfails on main in Day and Week withEnter did not show the selected event's notes, then passes here. Clock, layout, whitespace, DST, URL-launcher and in-flight-edit regressions also fail before their fixes and pass afterward.Build, formatting, vet, lint, surface, skill-sync and release-lockstep checks pass. Internal tests and TUI race tests pass excluding one environment-dependent MIME test. Full
make testfails that same test unchanged on main because this container lacks file(1). Local tidy is blocked by an uncached indirect module with network module lookup disabled. Full CI must pass before merge.Recorded the real base and fixed binaries against demo data. The final recording shows Day and Week opening, long-note scrolling, closing, and the edit transition without saving. Independent review approves the final committed diff.
Summary by cubic
Enter now opens a read-only card showing a selected event's details in Calendar's Day, Week, and Year views instead of doing nothing. The card is built from the grid's already-loaded recording, so no extra fetch is needed, and it shows timing, location, link, guests, and notes.
oopens only http/https links;file://paths and application schemes are shown but never handed to the launcher.eswaps the card for the edit form on the same event,escorqcloses it, and arrows or Page Up/Down scroll long notes.wrapTextnow measures terminal cells and hard-wraps long tokens at grapheme boundaries.Addresses Enter does nothing on a highlighted event.
Written for commit 2a8efa5. Summary will update on new commits.