️(fetch) only fetch visible calendars + try single query expanded

This commit is contained in:
Sylvain Zimmer
2026-02-10 10:53:39 +01:00
parent 659029dd1f
commit 797d92ff62

View File

@@ -151,76 +151,86 @@ export const useSchedulerInit = ({
return visibleCalendarUrlsRef.current.has(eventCalendarUrl); return visibleCalendarUrlsRef.current.has(eventCalendarUrl);
}, },
// Event sources - fetch from ALL CalDAV calendars (filtering done by eventFilter) // Event sources - fetch only from visible calendars
eventSources: [ eventSources: [
{ {
events: async (fetchInfo: EventCalendarFetchInfo) => { events: async (fetchInfo: EventCalendarFetchInfo) => {
const calendars = davCalendarsRef.current; const calendars = davCalendarsRef.current;
if (calendars.length === 0) return []; if (calendars.length === 0) return [];
// Only fetch events for calendars the user has toggled visible
const visibleCalendars = calendars.filter(
(c) => visibleCalendarUrlsRef.current.has(c.url)
);
if (visibleCalendars.length === 0) return [];
try { try {
// Fetch events from ALL calendars in parallel const calendarColors = adapter.createCalendarColorMap(calendars);
const allEventsPromises = calendars.map(async (calendar) => { const timeRange = {
const timeRange = { start: fetchInfo.start,
start: fetchInfo.start, end: fetchInfo.end,
end: fetchInfo.end, };
};
// Fetch source events and expanded instances in parallel // Single expanded fetch per visible calendar
const [sourceEventsResult, expandedEventsResult] = await Promise.all([ const allEventsPromises = visibleCalendars.map(async (calendar) => {
caldavService.fetchEvents(calendar.url, { timeRange, expand: false }), const result = await caldavService.fetchEvents(
caldavService.fetchEvents(calendar.url, { timeRange, expand: true }), calendar.url, { timeRange, expand: true }
]); );
if (!expandedEventsResult.success || !expandedEventsResult.data) { if (!result.success || !result.data) {
console.error( console.error(
`Failed to fetch events from ${calendar.url}:`, `Failed to fetch events from ${calendar.url}:`,
expandedEventsResult.error result.error
); );
return []; return [];
} }
// Build a map of source recurrence rules by UID // Check if any expanded instances need recurrence rules
const sourceRulesByUid = new Map<string, unknown>(); const uidsNeedingRules = new Set<string>();
if (sourceEventsResult.success && sourceEventsResult.data) { for (const evt of result.data) {
for (const sourceEvent of sourceEventsResult.data) { for (const icsEvent of evt.data.events ?? []) {
const icsEvents = sourceEvent.data.events ?? []; if (icsEvent.recurrenceId && !icsEvent.recurrenceRule) {
for (const icsEvent of icsEvents) { uidsNeedingRules.add(icsEvent.uid);
if (icsEvent.recurrenceRule && !icsEvent.recurrenceId) { }
sourceRulesByUid.set(icsEvent.uid, icsEvent.recurrenceRule); }
}
// Only fetch source events if we actually need recurrence rules
let sourceRulesByUid = new Map<string, unknown>();
if (uidsNeedingRules.size > 0) {
const sourceResult = await caldavService.fetchEvents(
calendar.url, { timeRange, expand: false }
);
if (sourceResult.success && sourceResult.data) {
for (const sourceEvent of sourceResult.data) {
for (const icsEvent of sourceEvent.data.events ?? []) {
if (icsEvent.recurrenceRule && !icsEvent.recurrenceId) {
sourceRulesByUid.set(icsEvent.uid, icsEvent.recurrenceRule);
}
} }
} }
} }
} }
// Enrich expanded events with recurrence rules from sources // Enrich expanded events with recurrence rules from sources
const enrichedExpandedData = expandedEventsResult.data.map( const enrichedData = uidsNeedingRules.size > 0
(event) => { ? result.data.map((event) => ({
const enrichedEvents = event.data.events?.map((icsEvent) => {
// If this is an instance without recurrenceRule, add it from source
if (icsEvent.recurrenceId && !icsEvent.recurrenceRule) {
const sourceRule = sourceRulesByUid.get(icsEvent.uid);
if (sourceRule) {
return { ...icsEvent, recurrenceRule: sourceRule };
}
}
return icsEvent;
});
return {
...event, ...event,
data: { data: {
...event.data, ...event.data,
events: enrichedEvents, events: event.data.events?.map((icsEvent) => {
if (icsEvent.recurrenceId && !icsEvent.recurrenceRule) {
const rule = sourceRulesByUid.get(icsEvent.uid);
if (rule) return { ...icsEvent, recurrenceRule: rule };
}
return icsEvent;
}),
}, },
}; }))
} : result.data;
);
const calendarColors = adapter.createCalendarColorMap(calendars);
// Type assertion needed due to the enrichment process
return adapter.toEventCalendarEvents( return adapter.toEventCalendarEvents(
enrichedExpandedData as typeof expandedEventsResult.data, enrichedData as typeof result.data,
{ calendarColors } { calendarColors }
); );
}); });