fix: save a calendar's default reminders when another calendar uses the ids of the ones kept

This commit is contained in:
Linus Rath
2026-10-29 04:50:15 +01:00
parent 6133bcd951
commit b767df9fad
2 changed files with 53 additions and 2 deletions
@@ -0,0 +1,30 @@
import { describe, it, expect, vi } from 'vitest';
// The calendar sheet's default reminders. Alert ids must be unique in the
// account on Stalwart 1.0: an alert the lists can't show kept the id
// another client gave it, and when another calendar used that id too, the
// whole Calendar/set was refused, the new name and colour with it.
vi.mock('../icons', () => ({ Check: () => null, Plus: () => null, X: () => null }));
vi.mock('../Button', () => ({ default: () => null }));
vi.mock('../../lib/use-layout', () => ({ useSheetInsets: () => ({}) }));
vi.mock('../../theme/colors', () => ({ useColors: () => ({}) }));
import type { Alert } from '../../api/types';
import { defaultAlertsToSave } from '../calendar/CalendarEditSheet';
// An email alert: the reminder lists show display alerts only.
const email: Alert = { '@type': 'Alert', trigger: { '@type': 'OffsetTrigger', offset: '-PT30M', relativeTo: 'start' }, action: 'email' };
describe('the default alerts a calendar saves', () => {
it('puts the alerts it keeps under the calendar\'s own ids too', () => {
const timed = defaultAlertsToSave({ id: 'acc-2:b', originalId: 'b' }, false, [{ minutesBefore: 10 }], { 'default-1': email });
const allDay = defaultAlertsToSave({ id: 'b' }, true, [], { x1: email });
expect(timed).toEqual({
'cal-b-timed-1': email,
'cal-b-timed-2': expect.objectContaining({ action: 'display' }),
});
expect(allDay).toEqual({ 'cal-b-allday-1': email });
});
});
+23 -2
View File
@@ -110,6 +110,27 @@ function DefaultRemindersEditor({
);
}
/**
* The default alerts saved for `calendar`'s timed or all-day events: the
* reminders, and the alerts the lists can't show (`kept`), every one under
* the calendar's own id prefix. Ids must be unique in the account, and a kept
* alert had the id another client gave it: when another calendar used that
* id too, Stalwart 1.0 refused the whole Calendar/set, its name and colour
* with it.
*/
export function defaultAlertsToSave(
calendar: Pick<Calendar, 'id' | 'originalId'>,
allDay: boolean,
reminders: Reminder[],
kept: Record<string, Alert>,
): Record<string, Alert> {
const prefix = defaultAlertIdPrefix(calendar, allDay);
const rekeyed: Record<string, Alert> = {};
let n = 0;
for (const alert of Object.values(kept)) rekeyed[`${prefix}-${++n}`] = alert;
return remindersToDefaultAlerts(reminders, rekeyed, prefix);
}
interface CalendarEditSheetProps {
visible: boolean;
// Existing calendar to edit; null creates a new one.
@@ -161,10 +182,10 @@ export function CalendarEditSheet({ visible, calendar, onSave, onClose }: Calend
const values: CalendarEditValues = { name: trimmed, color, description: description.trim() };
// Ids unique in the account: Stalwart 1.0 refuses one another calendar uses.
if (calendar && editsDefaults && !sameReminders(timedReminders, initialTimed)) {
values.defaultAlertsWithTime = remindersToDefaultAlerts(timedReminders, keptTimed, defaultAlertIdPrefix(calendar, false));
values.defaultAlertsWithTime = defaultAlertsToSave(calendar, false, timedReminders, keptTimed);
}
if (calendar && editsDefaults && !sameReminders(allDayReminders, initialAllDay)) {
values.defaultAlertsWithoutTime = remindersToDefaultAlerts(allDayReminders, keptAllDay, defaultAlertIdPrefix(calendar, true));
values.defaultAlertsWithoutTime = defaultAlertsToSave(calendar, true, allDayReminders, keptAllDay);
}
await onSave(values);
onClose();