diff --git a/__test__/components/Calendar.test.tsx b/__test__/components/Calendar.test.tsx
index ed3dd23..f699d55 100644
--- a/__test__/components/Calendar.test.tsx
+++ b/__test__/components/Calendar.test.tsx
@@ -135,7 +135,7 @@ describe("CalendarSelection", () => {
},
},
},
- pending: false,
+ pending: true,
},
};
it("renders calendars", async () => {
@@ -340,7 +340,7 @@ describe("calendar Availability search", () => {
events: {},
},
},
- pending: false,
+ pending: true,
templist: {},
},
};
@@ -495,12 +495,20 @@ describe("calendar Availability search", () => {
}, 15000);
it("BUGFIX: can untoggle all calendar.personal", async () => {
+ jest
+ .spyOn(calendarDetailThunks, "getCalendarDetailAsync")
+ .mockImplementation(
+ () =>
+ ({
+ type: "getCalendarDetailAsync",
+ unwrap: () => Promise.resolve({}),
+ }) as any
+ );
await act(async () =>
renderWithProviders(, {
user: preloadedState.user,
calendars: {
list: { "user1/cal1": preloadedState.calendars.list["user1/cal1"] },
- pending: false,
},
})
);
@@ -572,8 +580,8 @@ describe("calendar Availability search", () => {
calendarApi.changeView("dayGridMonth");
fireEvent.click(screen.getByTestId("ChevronRightIcon"));
});
- expect(spy).toHaveBeenCalledTimes(4);
- const callArgs = spy.mock.calls[3][0];
+ expect(spy).toHaveBeenCalledTimes(2);
+ const callArgs = spy.mock.calls[1][0];
expect(callArgs.calId).toBe("user1/cal1");
const startDate = new Date(
@@ -621,10 +629,13 @@ describe("calendar Availability search", () => {
const spy = jest
.spyOn(calendarDetailThunks, "getCalendarDetailAsync")
- .mockImplementation(() => ({
- type: "getCalendarDetailAsync",
- unwrap: () => Promise.resolve({}),
- })) as any;
+ .mockImplementation(
+ () =>
+ ({
+ type: "getCalendarDetailAsync",
+ unwrap: () => Promise.resolve({}),
+ }) as any
+ );
await act(async () => {
renderWithProviders(
@@ -675,10 +686,13 @@ describe("calendar Availability search", () => {
const spy = jest
.spyOn(calendarDetailThunks, "getCalendarDetailAsync")
- .mockImplementation(() => ({
- type: "getCalendarDetailAsync",
- unwrap: () => Promise.resolve({}),
- })) as any;
+ .mockImplementation(
+ () =>
+ ({
+ type: "getCalendarDetailAsync",
+ unwrap: () => Promise.resolve({}),
+ }) as any
+ );
await act(async () => {
renderWithProviders(
@@ -708,10 +722,13 @@ describe("calendar Availability search", () => {
it("does not make duplicate API calls for same calendar and range", async () => {
const spy = jest
.spyOn(calendarDetailThunks, "getCalendarDetailAsync")
- .mockImplementation(() => ({
- type: "getCalendarDetailAsync",
- unwrap: () => Promise.resolve({}),
- })) as any;
+ .mockImplementation(
+ () =>
+ ({
+ type: "getCalendarDetailAsync",
+ unwrap: () => Promise.resolve({}),
+ }) as any
+ );
await act(async () => {
renderWithProviders(
diff --git a/src/components/Calendar/Calendar.tsx b/src/components/Calendar/Calendar.tsx
index ea3324d..00887d6 100644
--- a/src/components/Calendar/Calendar.tsx
+++ b/src/components/Calendar/Calendar.tsx
@@ -13,6 +13,7 @@ import {
} from "@/utils/dateUtils";
import { extractEventBaseUuid } from "@/utils/extractEventBaseUuid";
import { setSelectedCalendars as setSelectedCalendarsToStorage } from "@/utils/storage/setSelectedCalendars";
+import { useSelectedCalendars } from "@/utils/storage/useSelectedCalendars";
import { browserDefaultTimeZone } from "@/utils/timezone";
import { CalendarApi, DateSelectArg } from "@fullcalendar/core";
import frLocale from "@fullcalendar/core/locales/fr";
@@ -76,11 +77,14 @@ export default function CalendarApp({
(state) => state.settings.hideDeclinedEvents
);
const calendars = useAppSelector((state) => state.calendars.list);
+ const isPending = useAppSelector((state) => state.calendars.pending);
const displayWeekNumbers = useAppSelector(
(state) => state.settings.displayWeekNumbers
);
const tempcalendars = useAppSelector((state) => state.calendars.templist);
- const [selectedCalendars, setSelectedCalendars] = useState([]);
+ const storedCalendars = useSelectedCalendars();
+ const [selectedCalendars, setSelectedCalendars] =
+ useState(storedCalendars);
const calendarLightSignature = useMemo(() => {
return Object.values(calendars || {})
@@ -253,6 +257,8 @@ export default function CalendarApp({
}, [rangeKey]);
useEffect(() => {
+ if (isPending) return;
+
if (!rangeKey || sortedSelectedCalendars.length === 0) {
activeLoadCompletedRef.current = true;
setActiveLoadCompleted(true);
@@ -320,8 +326,7 @@ export default function CalendarApp({
}, [dispatch, rangeKey, sortedSelectedCalendars, rangeStart, rangeEnd]);
useEffect(() => {
- if (!rangeKey || !activeLoadCompleted) return;
-
+ if (!rangeKey || !activeLoadCompleted || isPending) return;
const hiddenCalendars = calendarIds
.filter((id) => !selectedCalendars.includes(id))
.filter((id) => {
@@ -355,6 +360,7 @@ export default function CalendarApp({
rangeStart,
rangeEnd,
activeLoadCompleted,
+ isPending,
]);
const calendarsWithClearedCache = useMemo(() => {
@@ -369,6 +375,7 @@ export default function CalendarApp({
const processedCacheClearRef = useRef>({});
useEffect(() => {
+ if (isPending) return;
calendarsWithClearedCache.forEach(({ id, cleared }) => {
if (processedCacheClearRef.current[id] === cleared) {
return;
@@ -397,7 +404,14 @@ export default function CalendarApp({
prefetchedCalendarsRef.current[id] = "";
});
});
- }, [calendarsWithClearedCache, dispatch, rangeKey, rangeStart, rangeEnd]);
+ }, [
+ calendarsWithClearedCache,
+ dispatch,
+ rangeKey,
+ rangeStart,
+ rangeEnd,
+ isPending,
+ ]);
useEffect(() => {
const currentIds = new Set(tempCalendarIds);
diff --git a/src/features/Calendars/CalendarSlice.ts b/src/features/Calendars/CalendarSlice.ts
index 17353e0..83b32fb 100644
--- a/src/features/Calendars/CalendarSlice.ts
+++ b/src/features/Calendars/CalendarSlice.ts
@@ -28,7 +28,7 @@ const CalendarSlice = createSlice({
initialState: {
list: {} as Record,
templist: {} as Record,
- pending: false,
+ pending: true,
error: null as string | null,
} as {
list: Record;
diff --git a/src/utils/storage/useSelectedCalendars.ts b/src/utils/storage/useSelectedCalendars.ts
index 7689f0d..180324c 100644
--- a/src/utils/storage/useSelectedCalendars.ts
+++ b/src/utils/storage/useSelectedCalendars.ts
@@ -2,6 +2,7 @@ import { useEffect, useState } from "react";
export function useSelectedCalendars(): string[] {
const [calendars, setCalendars] = useState(() => {
+ if (typeof window === "undefined") return [];
try {
return JSON.parse(localStorage.getItem("selectedCalendars") ?? "[]");
} catch {
@@ -10,6 +11,8 @@ export function useSelectedCalendars(): string[] {
});
useEffect(() => {
+ if (typeof window === "undefined") return;
+
const onStorage = (e: StorageEvent) => {
if (e.key === "selectedCalendars") {
try {
diff --git a/src/websocket/WebSocketGate.tsx b/src/websocket/WebSocketGate.tsx
index 6cefb3d..cb73e00 100644
--- a/src/websocket/WebSocketGate.tsx
+++ b/src/websocket/WebSocketGate.tsx
@@ -17,6 +17,7 @@ export function WebSocketGate() {
);
const [isSocketOpen, setIsSocketOpen] = useState(false);
+ const isPending = useAppSelector((state) => state.calendars.pending);
const calendarList = useSelectedCalendars();
const tempCalendarList = Object.keys(
@@ -73,13 +74,15 @@ export function WebSocketGate() {
// Register using a diff with previous calendars
useEffect(() => {
+ if (isPending) return;
+
syncCalendarRegistrations(
isSocketOpen,
socketRef,
calendarList,
previousCalendarListRef
);
- }, [isSocketOpen, calendarList]);
+ }, [isSocketOpen, calendarList, isPending]);
useEffect(() => {
syncCalendarRegistrations(