mirror of
https://github.com/bulwarkmail/native.git
synced 2026-10-31 08:06:36 +00:00
fix: keep the edits when the recurring event question is cancelled
This commit is contained in:
@@ -13,6 +13,7 @@ import {
|
||||
timePattern,
|
||||
layoutOverlappingEvents,
|
||||
CALENDAR_COLOR_PALETTE,
|
||||
reopenedEdit,
|
||||
} from '../calendar-utils';
|
||||
import type { CalendarEvent } from '../../api/types';
|
||||
import { useSettingsStore } from '../../stores/settings-store';
|
||||
@@ -278,3 +279,18 @@ describe('layoutOverlappingEvents', () => {
|
||||
expect(layoutOverlappingEvents(events, day)).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('reopenedEdit', () => {
|
||||
it('puts the unsaved edits over the event and drops cleared fields', () => {
|
||||
const event = {
|
||||
id: 'e1', title: 'Team sync', start: '2026-10-19T10:00:00', duration: 'PT30M',
|
||||
locations: { l: { '@type': 'Location', name: 'Room 2' } },
|
||||
} as unknown as CalendarEvent;
|
||||
const reopened = reopenedEdit(event, { title: 'Team sync (moved)', start: '2026-10-19T11:00:00', locations: null });
|
||||
expect(reopened.id).toBe('e1');
|
||||
expect(reopened.title).toBe('Team sync (moved)');
|
||||
expect(reopened.start).toBe('2026-10-19T11:00:00');
|
||||
expect(reopened.duration).toBe('PT30M');
|
||||
expect('locations' in reopened).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -604,3 +604,17 @@ export function getPrimaryCalendarId(
|
||||
): string | undefined {
|
||||
return Object.keys(event.calendarIds || {})[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* The event as the editor last had it: the stored event with the unsaved
|
||||
* edits on top, a field cleared in the editor (sent as `null`) removed. Used
|
||||
* to reopen the editor when the recurrence-scope question is cancelled.
|
||||
*/
|
||||
export function reopenedEdit(event: CalendarEvent, updates: Partial<CalendarEvent>): CalendarEvent {
|
||||
const merged: Record<string, unknown> = { ...event };
|
||||
for (const [key, value] of Object.entries(updates)) {
|
||||
if (value === null) delete merged[key];
|
||||
else if (value !== undefined) merged[key] = value;
|
||||
}
|
||||
return merged as unknown as CalendarEvent;
|
||||
}
|
||||
|
||||
@@ -86,6 +86,7 @@ import {
|
||||
getTaskDueDate,
|
||||
pickUnusedCalendarColor,
|
||||
sharedCalendarColorKey,
|
||||
reopenedEdit,
|
||||
} from '../lib/calendar-utils';
|
||||
import { buildReplyTo } from '../lib/calendar-invitation';
|
||||
import {
|
||||
@@ -825,6 +826,16 @@ export default function CalendarScreen() {
|
||||
[modalEvent, createEvent, updateEvent],
|
||||
);
|
||||
|
||||
// Cancelling "which occurrences?" after editing a recurring event goes back
|
||||
// to the editor with the edits still in it; they used to be thrown away.
|
||||
const cancelScope = React.useCallback(() => {
|
||||
const pending = pendingAction;
|
||||
setPendingAction(null);
|
||||
if (pending?.kind !== 'edit') return;
|
||||
setModalEvent(reopenedEdit(pending.event, pending.updates));
|
||||
setModalVisible(true);
|
||||
}, [pendingAction]);
|
||||
|
||||
const handleDeleteFromModal = React.useCallback(
|
||||
async (event: CalendarEvent) => {
|
||||
setModalVisible(false);
|
||||
@@ -1232,7 +1243,7 @@ export default function CalendarScreen() {
|
||||
visible={!!pendingAction}
|
||||
actionType={pendingAction?.kind ?? 'edit'}
|
||||
onSelect={handleScopeSelect}
|
||||
onClose={() => setPendingAction(null)}
|
||||
onClose={cancelScope}
|
||||
/>
|
||||
|
||||
<CalendarSidebarDrawer
|
||||
|
||||
Reference in New Issue
Block a user