Sidebar Meetings subtitle shows a future all-day event as if it were today
Summary
In the left sidebar, the Meetings nav item subtitle shows the wrong event: an all-day event weeks in the future is displayed ahead of a nearer timed event, and it is rendered without any date qualifier — so it reads as if it is happening today.
Concretely: I have an all-day recurring event on Sept 9 and a timed event on Aug 31. On Aug 28 the sidebar reads:
Meetings
Wedding Anniversary · All day…while the Meetings pane itself correctly shows "No events today" for Aug 28 and lists the Aug 31 event next. The two surfaces disagree.
Steps to reproduce
- Have an all-day Google Calendar event some days out (e.g. Sept 9), and a timed event sooner (e.g. Aug 31).
- Open the app on a day before both (e.g. Aug 28).
- Look at the Meetings item in the left sidebar vs. the Meetings pane.
Expected: subtitle reflects the genuinely next event (Aug 31), or at minimum qualifies the all-day event with its date.
Actual: subtitle shows the Sept 9 all-day event as Wedding Anniversary · All day, reading as today.
Root cause
Two issues in the renderer compound. Both are visible in the built bundle (renderer/dist/assets/index-*.js); names below are minified.
1. All-day events are hoisted to the front of the list regardless of date.
.sort((a, b) =>
a.isAllDay !== b.isAllDay
? (a.isAllDay ? -1 : 1)
: a.start.getTime() - b.start.getTime())This comparator appears twice. It is correct for ordering within a single day (all-day items belong at the top of a day column), but it is also applied to the multi-day "upcoming" list that the sidebar reads via ce[0]. Any all-day event therefore outranks every timed event, no matter how far out it is.
Simulating the comparator with the two events above:
[0] Wedding Anniversary 2026-09-09 allDay=True <-- selected as ce[0]
[1] DATASCI 2026-08-31 allDay=False2. The subtitle formatter returns early for all-day events, skipping the date qualifier.
function Wor(e){
if (e.isAllDay) return "All day"; // <-- returns before any date logic
const t = new Date, n = new Date(t); n.setDate(n.getDate()+1);
const r = e.start.toLocaleTimeString([], {hour:"numeric", minute:"2-digit"});
return Z8e(e.start, t) ? r
: Z8e(e.start, n) ? `Tmrw ${r}`
: e.start.toLocaleDateString([], {...});
}Timed events get today / Tmrw / explicit-date treatment. All-day events never reach it, so a far-future all-day event is labelled identically to one occurring today.
The Meetings pane is unaffected because it buckets events by actual date over a fixed day window, so the Sept 9 event simply falls outside the window.
Suggested fix
- Sort the multi-day upcoming list by
startalone; keep theisAllDay-first comparator scoped to within-day grouping. - In the subtitle formatter, apply the same today / tomorrow / date qualification to all-day events, e.g.
All daywhen it is today andSep 9 · All dayotherwise.
Impact
Affects any all-day event — birthdays, holidays, OOO blocks — not just this one. For calendars carrying a recurring all-day event, the sidebar can be persistently wrong and appear to announce a personal occasion on the wrong day.
Environment
- Rowboat 0.9.1 (latest release at time of filing)
- macOS (Darwin 25.5.0), Apple Silicon
- Google Calendar via native OAuth (
calendar.events.readonly)
Source: rowboatlabs/rowboat