Commit Graph
9 Commits
Author SHA1 Message Date
Linus Rath f7d1a86b5e fix: keep series intact when a split fails and when edited from one occurrence
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.
2026-09-26 02:48:11 +02:00
Linus Rath 6d4b695489 fix: ask attendees again when their organizer drags a meeting
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).
2026-09-26 00:25:27 +02:00
Linus Rath 75b432e957 fix: reach attendees who answered with series splits and first edits
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).
2026-09-26 00:23:28 +02:00
Linus Rath 2cf38e863b fix: show titles on occurrences answered by reply stubs on Stalwart 1.0
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`.
2026-09-25 19:37:41 +02:00
Linus Rath d0b0383660 fix: apply recurrence overrides as patches in browser expansion
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.
2026-09-25 17:42:59 +02:00
Linus Rath 990c5e0f77 fix: edit or answer one occurrence of a series on Stalwart 1.0
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
2026-09-25 17:40:49 +02:00
Linus Rath 28fd880582 fix: keep single-occurrence edits on that occurrence and keep its details 2026-09-23 13:40:01 +02:00
Linus Rath f95b826434 feat: let attendees answer a single occurrence of a recurring event #1086 2026-09-23 13:06:41 +02:00
Linus Rath d800689924 feat: use Stalwart synthetic ids for recurring occurrences #140 2026-08-29 11:03:48 +02:00