Edits of a recurring meeting from one of its occurrences went wrong in
several ways (live on 1.0 and 0.16.23, attendees included):
- A "this and following" split whose new series could not be created
stayed half done: the calendar store answers most failures with null,
and only a thrown error put the old series back. The series stayed
ended, told so to the attendees, and the save said it had worked. A
null now puts the series back as well and fails the save. The rollback
writes the old overrides back as a whole map: a pointer into a series
without overrides fails, and the split may just have removed its only
one.
- "This occurrence" on the series itself (a meeting opened from a link
or a search result) went out in one write that reached no attendee
who had answered. It now takes the same two steps as an occurrence of
an expanded series: the override as it is without messages, then the
change of it.
- The new series of a split started at the opened occurrence's own time
and in the user's zone: Mondays in New York, one occurrence moved to
Tuesday, renamed from there by a user in Berlin, became a Tuesday
series in Berlin. It now goes on from that occurrence's recurrence id,
in the series' zone, moved only by what the editor moved; the
occurrence keeps its own time through its override. It takes the old
series' details with what the user changed, not the opened
occurrence's own ones.
- "All events" from an occurrence with an override of its own wrote that
occurrence's own title, copied into its override, back to the series:
a new room there renamed the series. Only the fields the user changed
go to the series now; the opened occurrence's override takes them too
(on 1.0 also where it holds them as pointers), and other overrides
where they only held the series' old value.
- The move of an "all" edit was measured on the user's clock: across a
week in which only one of the two zones changes to or from summer
time, the series moved an hour more or less than picked. It is now
measured on the series' own clock.
- 0.16 (0.16.23 checked) reads a rule's UNTIL as the series' wall clock
taken for UTC, so in a zone behind UTC a split or "delete this and
following" kept the occurrence it was to end before. The UNTIL is now
earlier by the zone's offset, which ends the series there on 0.16 and
1.0 alike.
- An applied counter proposal for one occurrence of a recurring meeting
went to the first event with its uid. It now goes to the occurrence
the proposal names; one for a whole series of which only occurrences
are in view is not applied to any of them.
A move outside the editor kept every answer. A drag or resize in the
week and day views, a drop in the month view and an applied counter
proposal wrote the new time with the attendees' stored answers:
Stalwart's update then said "accepted" for a time nobody had accepted,
and a dragged occurrence, which gets its own override, reached no
attendee who had answered (live on 1.0 and 0.16.23). When the user
organizes the meeting these moves now ask the attendees again, as the
editor does; one helper (`userOrganizes`) decides for both.
Also:
- A changed recurrence rule counts as a move for the series: a custom
rule moved from Monday to Tuesday asks again. A rule the user did not
touch is no change however the server spells it, and on one
occurrence, where no rule applies, it is none.
- An event that lasts no time (a deadline) keeps its zero length on
save instead of becoming an hour long and asking everyone again.
- An attendee's save of their own copy - an alert on one occurrence, a
drag - wrote the participants again and sent the organizer a
"Reply:" mail. It now leaves the participants alone and sends
nothing. The editor shows someone else's attendee list read-only and
no "Send invitations" box, which only ever controlled the organizer's
messages; answers go out through the answer buttons.
- An existing override written on the base event (0.16 before 0.16.20,
and ranges the browser expands) gets the series' organizer again when
it has none, as every save wrote it before 4c20b09c: 0.16.19 refuses
an answer to such an occurrence. 0.16.23 takes the key and drops it;
1.0 refuses it inside an override once, and the store writes the
override again without it (both live).
- The comment on `organizerCalendarAddress` said Stalwart takes the
ORGANIZER solely from it. Both versions take it from the owner
participant when it is missing (live).
Stalwart sends a new event, and an occurrence that gets its own override
for the first time, only to attendees who have not answered (PARTSTAT
absent or NEEDS-ACTION); a change to an existing event or override goes
to everyone who has not declined. Since the editor keeps the attendees'
answers on a save (4c20b09c), two edits never reached the attendees who
had accepted (live on 1.0 and 0.16.23):
- "This and following events" made the rest of the series a new event
with the answers the old one had, so those attendees got nothing, and
it ended the old series without scheduling messages, so they kept
every occurrence of it. The new series now asks every attendee again,
and the old one is shortened with scheduling messages when the user
organizes it and sends invitations; a failed create puts it back the
same way. Deleting "this and following events" ends the series the
same way.
- The first change to one occurrence that keeps the answers - a new
title, another room - was sent only to attendees who had not
answered. When the user organizes the event, sends invitations and
an attendee has answered, the store now gives the occurrence its
override first, as it is and without messages, finds it again
(0.16.20 renumbers synthetic ids once an override exists) and then
writes the change with messages. The attendee gets the update and
keeps their answer. This works through synthetic ids (0.16.20 on,
1.0) and as an override on the base event (older 0.16, and ranges
expanded in the browser).
Stalwart 0.16 stored an attendee's answer to one occurrence as an
override holding little more than that attendee, without SUMMARY,
LOCATION or DESCRIPTION. On 0.16 the occurrence was listed twice and
Bulwark merged the pair; 1.0 builds such an occurrence from the
override alone, so after an upgrade it shows untitled.
When occurrences are hydrated from their base event, take a missing
title from the series unless the override sets one itself, and the
place and description as well when the override removes the title,
which is what a stub looks like as 1.0 returns it. The base event get
now also asks for `title`, `locations` and `description`.
Stalwart 1.0 returns recurrence overrides as RFC 8984 PatchObjects, with
keys like participants/p1/participationStatus and nulls that remove.
Browser expansion spread them onto the occurrence, so a declined
occurrence stayed accepted and the pointer keys became junk properties.
Moved or resized occurrences also kept the time and length the rule
gave them and were placed by their original date.
Overrides are now applied as patches, occurrence times come from the
patched start, time zone and duration, and new changes merge into an
existing override without keys that are prefixes of one another.
Stalwart 1.0 refuses series properties such as privacy and the
organizer on a single occurrence unless they repeat the series' value,
and refuses them inside a recurrence override on the base event. The
event modal sent privacy "public" on every save, so editing one
occurrence of a series without CLASS failed, and so did every change to
an occurrence the browser expanded.
- leave series and per-event keys out of changes to one occurrence
- write base-event overrides as before and, if the server refuses
series keys there, repeat the write once without them and remember
that
- stop resetting status, free/busy and privacy when an event is edited