#932·rowboat

Sidebar Meetings subtitle shows a future all-day event as if it were today

Author: h6y3Created Aug 29, 2026Updated Sep 11, 2026

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

  1. Have an all-day Google Calendar event some days out (e.g. Sept 9), and a timed event sooner (e.g. Aug 31).
  2. Open the app on a day before both (e.g. Aug 28).
  3. 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.

javascript
.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=False

2. The subtitle formatter returns early for all-day events, skipping the date qualifier.

javascript
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 start alone; keep the isAllDay-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 day when it is today and Sep 9 · All day otherwise.

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)