api.tasks.create and update take alerts by id: a trigger from the task's
due (or start) as an ISO 8601 duration, or at an instant in UTC; display
or email; at most five. An update merges by id, each alert written by its
JMAP patch path: an alert given is set, one given null is removed, and
alerts the plugin did not name, such as one another app wrote, stay as
the server holds them; null for the whole map removes every alert.
Whether the map is patched or written whole is decided on the task as the
server holds it, not an older copy. An alert kept with the same trigger
and action stays acknowledged, so a snooze is an update of its trigger,
which then fires again. While a task uses its calendar's default alerts,
a change makes them the task's own under new ids, as the task form does,
an alert under a default's id is refused rather than dropped, and
removing every alert turns the defaults off too.
TaskView returns the alerts, each with when it was acknowledged, and
useDefaultAlerts. api.tasks.acknowledgeAlert dismisses one alert (or
undoes that with null) by writing only its acknowledged. A plugin's
writes to one task go one after another, since Stalwart refuses a set
while another is under way on the same object. The task store applies
patch paths to the task the caller read, so a task the list does not
hold is shown and reported whole.
The task store was not cleared on an account switch, unlike the calendar,
contacts and the other account-scoped stores, so the next account showed
the previous one's tasks until its own arrived. And a fetch answered after
a later one had started still wrote its list: the outgoing account's
answer could put its tasks back after the switch, and an older answer
could replace a newer one.
clearAllStores now clears the tasks, and each fetch gets a number: only
the latest one's answer or error is kept, and clearing drops the fetches
still under way.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- send a calendar's colour only when the user changed it: Stalwart 1.0
accepts only #rgb, #rrggbb or a CSS name, so renaming a calendar that
another client coloured with an 8-digit hex (Apple Calendar) failed
- "Refresh cached data" kept nothing of the calendar store's persisted
state, so it deleted the user's iCal subscriptions, which exist only
there; keep them and drop the rest
- show a notice with a retry when the task list fails to load; it keeps
the tasks it had
- treat a method-level error on creating a task as a failure with its
JMAP type instead of "no id returned"
Stalwart Mail Server strictly validates JSCalendar task properties on CalendarEvent/set and rejects updates containing top-level progressUpdated with invalidProperties (RFC 8984 §5.2.2 only defined progressUpdated on Participant objects, obsoleted in JSCalendar 2.0).
- Omit progressUpdated from toggleTaskComplete in stores/task-store.ts
- Remove progressUpdated from CALENDAR_TASK_PROPERTIES in lib/jmap/client.ts
- Defensively strip progressUpdated in updateCalendarEvent and createCalendarTask
- Make progressUpdated optional in CalendarTask interface
- Add unit tests for task-store and JMAP client task methods
Stalwart's CalendarEvent/query ignores Task-type objects and does not
support the 'types' filter (returns unsupportedFilter error). This
caused tasks both locally created and from external clients like
Thunderbird to disappear on reload.
Root causes:
- CalendarEvent/query only returns @type:'Event' objects on Stalwart,
so tasks were invisible to the query endpoint.
- CALENDAR_EVENT_PROPERTIES lacked Task-specific fields (due, progress,
progressUpdated, priority), causing garbled data when tasks were
fetched with Event properties (e.g. utcStart:'32548-12-04T15:30:07Z').
Changes:
- Add CALENDAR_TASK_PROPERTIES with Task-specific fields (due, progress,
progressUpdated, priority).
- Rewrite getCalendarTasks() to first try CalendarEvent/query with
types:['Task'] filter, then fall back to CalendarEvent/get ids:null
which returns all calendar objects regardless of @type per JMAP spec.
- Rewrite createCalendarTask() to fetch back created tasks using
CALENDAR_TASK_PROPERTIES instead of piggybacking on createCalendarEvent.
- Add comprehensive debug logging throughout the task fetch/create flow
(TaskStore, JMAP client) visible when Debug Mode is enabled.
- Add 'types' field to CalendarEventFilter interface.