⚡️(fetch) only fetch visible calendars + try single query expanded
This commit is contained in:
@@ -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 }
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user