Skip to content

Open calendar event details on Enter - #591

Merged
robzolkos merged 10 commits into
mainfrom
agent/10424719303-hey-cli-418-enter-does-nothing-on-a-highlighted-
Oct 20, 2026
Merged

robzolkos merged 10 commits into
mainfrom
agent/10424719303-hey-cli-418-enter-does-nothing-on-a-highlighted-

Conversation

@robzolkos

@robzolkos robzolkos commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

🤖 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

  • Open details in Day, Week and inside a Year cell. Scroll notes, open hosted web links, close with Escape or q, and edit with e.
  • Synchronize late clock preferences, fit narrow layouts, omit blank metadata and correct all-day dates across daylight saving.
  • Use the current URL launcher, not the local attachment launcher. Edit the latest recording if an in-flight read completes under the card.
  • Correct stale habit and time-tracking shortcuts in the calendar documentation. Shared text wrapping now measures terminal cells and splits long tokens safely.

Addresses Enter does nothing on a highlighted event. No SDK or dependency changes.

Validation

go test ./internal/tui -run '^TestCalendarEnterShowsEventNotes$' -count=1 -v fails on main in Day and Week with Enter 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 test fails 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.

  • o opens only http/https links; file:// paths and application schemes are shown but never handed to the launcher. e swaps the card for the edit form on the same event, esc or q closes it, and arrows or Page Up/Down scroll long notes.
  • The card follows late clock preferences, fits narrow terminals, and omits blank fields. All-day events keep their inclusive end date in the grid and render correctly across daylight saving; only a timed event ending at midnight excludes the following day.
  • Calendar documentation now matches the actual keys for calendar spans, time tracking, and habits.
  • wrapText now 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.

View guided diff Turn on auto-fix

albertreig and others added 9 commits October 20, 2026 19:52
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.
Copilot AI balanced review requested due to automatic review settings October 20, 2026 20:09
@robzolkos
robzolkos requested a review from a team as a code owner October 20, 2026 20:09

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 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 run gh pr ready --undo.
Click "Ready for review" or run gh pr ready to 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

Comment thread internal/tui/event_detail.go Outdated
Comment on lines +210 to +211
if ends.Equal(time.Date(ends.Year(), ends.Month(), ends.Day(), 0, 0, 0, 0, ends.Location())) {
endDay = ends.AddDate(0, 0, -1)
@robzolkos

Copy link
Copy Markdown
Contributor Author

🤖 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 ends_at: 2026-10-22T00:00:00Z. The old card incorrectly showed October 21 while the edit form showed October 22.

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

go test ./internal/tui -run 'Test(AllDayEvent|EventCardAllDayEndAcrossDaylightSaving|CalendarOpensAllDayEventOnInclusiveEndDate|TimedMidnightEndDoesNotOccupyTheNextDay)' -count=1 -v fails on the previous head, including the event could not be opened on its inclusive final date, and passes with the fix. The timed-midnight regression remains green.

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.

@robzolkos
robzolkos merged commit c5fe278 into main Oct 20, 2026
25 checks passed
@robzolkos
robzolkos deleted the agent/10424719303-hey-cli-418-enter-does-nothing-on-a-highlighted- branch October 20, 2026 22:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants