diff --git a/__test__/features/Calendars/CalendarSlice.test.tsx b/__test__/features/Calendars/CalendarSlice.test.tsx index 42bfc53..4e90b50 100644 --- a/__test__/features/Calendars/CalendarSlice.test.tsx +++ b/__test__/features/Calendars/CalendarSlice.test.tsx @@ -330,7 +330,15 @@ describe("CalendarSlice", () => { it("getCalendarDetailAsync.fulfilled adds calendar events", () => { const payload = { calId: "c1", events: [{ uid: "e1" }] as any[] }; const state = reducer( - initialState, + { + ...initialState, + list: { + ["c1"]: { + id: "c1", + events: {}, + } as unknown as Calendars, + }, + }, getCalendarDetailAsync.fulfilled(payload, "req11", { calId: "c1", match: { start: "", end: "" }, diff --git a/src/components/Calendar/Calendar.tsx b/src/components/Calendar/Calendar.tsx index 2318ff2..7864525 100644 --- a/src/components/Calendar/Calendar.tsx +++ b/src/components/Calendar/Calendar.tsx @@ -211,6 +211,10 @@ export default function CalendarApp({ const [prevTempCalendars, setPrevTempCalendars] = useState([]); const [prevRangeKey, setPrevRangeKey] = useState(""); + const tempCalendarControllersRef = useRef>( + new Map() + ); + useEffect(() => { updateCalsDetails( Object.keys(tempcalendars), @@ -220,9 +224,21 @@ export default function CalendarApp({ prevRangeKey, dispatch, calendarRange, - "temp" + "temp", + tempCalendarControllersRef.current ); + prevTempCalendars.forEach((calId) => { + if (!Object.keys(tempcalendars).includes(calId)) { + const controller = tempCalendarControllersRef.current.get(calId); + if (controller) { + controller.abort(); + tempCalendarControllersRef.current.delete(calId); + } + delete fetchedRangesRef.current[calId]; + } + }); + setPrevTempCalendars(Object.keys(tempcalendars)); setPrevRangeKey(rangeKey); }, [rangeKey, Object.keys(tempcalendars).join(","), pending]); diff --git a/src/components/Calendar/utils/calendarUtils.ts b/src/components/Calendar/utils/calendarUtils.ts index 2147daf..968843c 100644 --- a/src/components/Calendar/utils/calendarUtils.ts +++ b/src/components/Calendar/utils/calendarUtils.ts @@ -107,7 +107,8 @@ export const updateCalsDetails = ( previousRangeKey: string, dispatch: Function, calendarRange: { start: Date; end: Date }, - calType?: "temp" + calType?: "temp", + controllers?: Map ) => { if (pending || !rangeKey) return; @@ -116,31 +117,65 @@ export const updateCalsDetails = ( ); newCalendars.forEach((id) => { - dispatch( - getCalendarDetailAsync({ - calId: id, - match: { - start: formatDateToYYYYMMDDTHHMMSS(calendarRange.start), - end: formatDateToYYYYMMDDTHHMMSS(calendarRange.end), - }, - calType, - }) - ); + if (controllers) { + const controller = new AbortController(); + controllers.set(id, controller); + + dispatch( + getCalendarDetailAsync({ + calId: id, + match: { + start: formatDateToYYYYMMDDTHHMMSS(calendarRange.start), + end: formatDateToYYYYMMDDTHHMMSS(calendarRange.end), + }, + calType, + signal: controller.signal, + }) + ); + } else { + dispatch( + getCalendarDetailAsync({ + calId: id, + match: { + start: formatDateToYYYYMMDDTHHMMSS(calendarRange.start), + end: formatDateToYYYYMMDDTHHMMSS(calendarRange.end), + }, + calType, + }) + ); + } }); if (rangeKey !== previousRangeKey) { selectedCalendars?.forEach((id) => { if (id) { - dispatch( - getCalendarDetailAsync({ - calId: id, - match: { - start: formatDateToYYYYMMDDTHHMMSS(calendarRange.start), - end: formatDateToYYYYMMDDTHHMMSS(calendarRange.end), - }, - calType, - }) - ); + if (controllers) { + const controller = new AbortController(); + controllers.set(id, controller); + + dispatch( + getCalendarDetailAsync({ + calId: id, + match: { + start: formatDateToYYYYMMDDTHHMMSS(calendarRange.start), + end: formatDateToYYYYMMDDTHHMMSS(calendarRange.end), + }, + calType, + signal: controller.signal, + }) + ); + } else { + dispatch( + getCalendarDetailAsync({ + calId: id, + match: { + start: formatDateToYYYYMMDDTHHMMSS(calendarRange.start), + end: formatDateToYYYYMMDDTHHMMSS(calendarRange.end), + }, + calType, + }) + ); + } } }); } diff --git a/src/features/Calendars/CalendarApi.ts b/src/features/Calendars/CalendarApi.ts index 1655f6e..3c45293 100644 --- a/src/features/Calendars/CalendarApi.ts +++ b/src/features/Calendars/CalendarApi.ts @@ -2,13 +2,15 @@ import { api } from "../../utils/apiUtils"; export async function getCalendars( userId: string, - scope: string = "personal=true&sharedDelegationStatus=accepted&sharedPublicSubscription=true&withRights=true" + scope: string = "personal=true&sharedDelegationStatus=accepted&sharedPublicSubscription=true&withRights=true", + signal?: AbortSignal ) { const calendars = await api .get(`dav/calendars/${userId}.json?${scope}`, { headers: { Accept: "application/calendar+json", }, + signal, }) .json(); return calendars; @@ -16,7 +18,8 @@ export async function getCalendars( export async function getCalendar( id: string, - match: { start: string; end: string } + match: { start: string; end: string }, + signal?: AbortSignal ) { const response = await api(`dav/calendars/${id}.json`, { method: "REPORT", @@ -26,6 +29,7 @@ export async function getCalendar( body: JSON.stringify({ match, }), + signal, }); const calendar = await response.json(); return calendar; diff --git a/src/features/Calendars/CalendarSlice.ts b/src/features/Calendars/CalendarSlice.ts index 35ebb32..34a49f4 100644 --- a/src/features/Calendars/CalendarSlice.ts +++ b/src/features/Calendars/CalendarSlice.ts @@ -171,13 +171,21 @@ export const getTempCalendarsListAsync = createAsyncThunk< export const getCalendarDetailAsync = createAsyncThunk< { calId: string; events: CalendarEvent[]; calType?: string }, - { calId: string; match: { start: string; end: string }; calType?: string }, + { + calId: string; + match: { start: string; end: string }; + calType?: string; + signal?: AbortSignal; + }, { rejectValue: RejectedError } >( "calendars/getCalendarDetails", - async ({ calId, match, calType }, { rejectWithValue }) => { + async ({ calId, match, calType, signal }, { rejectWithValue }) => { try { - const calendar = (await getCalendar(calId, match)) as Record; + const calendar = (await getCalendar(calId, match, signal)) as Record< + string, + any + >; const color = calendar["apple:color"]; const events: CalendarEvent[] = calendar._embedded["dav:item"].flatMap( (eventdata: any) => { @@ -736,10 +744,7 @@ const CalendarSlice = createSlice({ const type = action.payload.calType === "temp" ? "templist" : "list"; if (!state[type][action.payload.calId]) { - state[type][action.payload.calId] = { - id: action.payload.calId, - events: {}, - } as Calendars; + return; } action.payload.events.forEach((event) => { state[type][action.payload.calId].events[event.uid] = event; @@ -998,6 +1003,12 @@ const CalendarSlice = createSlice({ }) .addCase(getTempCalendarsListAsync.rejected, (state, action) => { state.pending = false; + if ( + action.payload?.message.includes("aborted") || + action.error.name === "AbortError" + ) { + return; + } state.error = action.payload?.message || action.error.message || @@ -1005,6 +1016,12 @@ const CalendarSlice = createSlice({ }) .addCase(getCalendarDetailAsync.rejected, (state, action) => { state.pending = false; + if ( + action.payload?.message.includes("aborted") || + action.error.name === "AbortError" + ) { + return; + } state.error = action.payload?.message || action.error.message || diff --git a/src/utils/apiUtils.ts b/src/utils/apiUtils.ts index 9706c60..48be742 100644 --- a/src/utils/apiUtils.ts +++ b/src/utils/apiUtils.ts @@ -11,9 +11,8 @@ export const api = ky.extend({ : null; const access_token = saved?.access_token; - const modifiedRequest = new Request(request); - modifiedRequest.headers.set("Authorization", `Bearer ${access_token}`); - return modifiedRequest; + request.headers.set("Authorization", `Bearer ${access_token}`); + return request; }, ], afterResponse: [