feat(todo): a project linked to a calendar shows its events beside the tasks (ADR 0033, D39)

A project's editor takes a calendar's address (https:// or webcal://,
refused otherwise), and its events show read-only, marked in the
project's colour: in Today's list and Upcoming's agenda above each day's
tasks, as blocks in the hour grids (Today's Calendar, Upcoming's 3-day)
sharing the lanes with timed tasks and all-day ones under All day, in
the project's Calendar (its agenda and month, its own events alone), and
in saved filters of days. A tap shows what an event is: when, where,
and whose calendar. The grid's lane layout is generic for it
(`layOutItems`); a task's row's box is shared (`rowBox`).

Whats-New: Link a calendar to a project in its settings: its events show beside your tasks in Today, Upcoming and the project.
Whats-New-De: Verknüpfe einen Kalender in den Einstellungen eines Projekts: Seine Termine erscheinen neben deinen Aufgaben in Heute, Demnächst und im Projekt.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
Tizian 「ティツィアーン」 2026-11-10 12:37:18 +01:00
commit 85a022af98
Signed by: raisondetredev
GPG key ID: 07F6FCF405488B64

View file

@ -766,7 +766,7 @@ Reactions are a list of emoji in the comment's payload, each once; a chip's tap
- *Fetched by the device, its address sealed* (the agent's, kept by the developer): the address is part of the project's sealed payload (`calendarUrl`), as a feed's address often is its only key, and each device fetches it itself over HTTPS, so the instance neither learns the address nor sees the events; a device keeps the last copy for when it is offline, not synced, as a file in the person's own folder on it (`calendars/<project>.ics`), as their reminders keep their tasks' titles unsealed on the device, and deleted with the link or the project. **Why not through the instance**, as Train's weather is: it would hold everyone's calendar addresses and see their events, for no gain but one fetch instead of one per device.
- *When*: as the app opens, every hour while it is open, and when a list is pulled down (`TaskRefresh`).
- *Read by a parser of our own, recurrence by `rrule`* (the developer's choice of three): the file's events (VEVENT: title, start, end or duration, all-day, place, cancelled, the dates a recurrence leaves out and the occurrences changed) are read by `ical.dart`, short and tested here; RFC 5545's recurrence rules, the large part easy to get wrong, are expanded by pub.dev's `rrule` (Apache-2.0); an event's time zone becomes the device's through `timezone`, already in the lock. **Rejected:** `icalendar_parser` beside `rrule` (one more dependency, less maintained, for the easy part), and recurrence of our own.
- *Shown as a task's date is*: an event becomes a day, a time and a duration on the device's clock, as `TaskDate`, so the lists, the agenda and the grids place it as they place tasks. It has no check, can't be dragged and opens nothing yet but its details.
- *Shown as a task's date is*: an event becomes a day, a time and a duration on the device's clock, as `TaskDate`, so the lists, the agenda and the grids place it as they place tasks. It has no check, can't be dragged and opens nothing yet but its details. A saved filter takes an event of the next four weeks where its days do (the agent's reading of *where a filter's days include them*): read as a task of its project on that day, with no priority or labels, the filter answers, and wouldn't for the same task without a date or a century later; so `today` or `7 days & #School` take events, and `#School`, `no date` or `p1 & today` none, a calendar's being endless. A label's screen takes none: events have no labels.
## Steps