Skip to content

Commit 787a23f

Browse files
committed
Extract AppRoot and SessionExpirationMonitor components, fix wrong toast on HMR
1 parent 6972b41 commit 787a23f

File tree

15 files changed

+47
-52
lines changed

15 files changed

+47
-52
lines changed

frontend/src/app-root.tsx

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { MetaProvider } from "@solidjs/meta";
2+
import { RouteSectionProps } from "@solidjs/router";
3+
import { Suspense } from "solid-js";
4+
import { Toaster } from "solid-sonner";
5+
import { SessionExpirationMonitor } from "~/components";
6+
import { I18nProvider } from "~/lib/i18n";
7+
import { PreferencesProvider } from "~/lib/preferences";
8+
import { ThemeProvider } from "~/lib/theme";
9+
10+
export const AppRoot = (props: RouteSectionProps) => {
11+
return (
12+
<MetaProvider>
13+
<PreferencesProvider>
14+
<I18nProvider>
15+
<ThemeProvider>
16+
<Suspense>{props.children}</Suspense>
17+
18+
<Toaster />
19+
<SessionExpirationMonitor />
20+
</ThemeProvider>
21+
</I18nProvider>
22+
</PreferencesProvider>
23+
</MetaProvider>
24+
);
25+
};

frontend/src/app.tsx

Lines changed: 2 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,11 @@
1-
import { MetaProvider } from "@solidjs/meta";
21
import { Router } from "@solidjs/router";
32
import { FileRoutes } from "@solidjs/start/router";
4-
import { Suspense } from "solid-js";
5-
import { Portal } from "solid-js/web";
6-
import { Toaster } from "solid-sonner";
7-
import { ThemeProvider } from "~/lib/theme";
8-
import { I18nProvider } from "~/lib/i18n";
9-
import { PreferencesProvider } from "~/lib/preferences";
3+
import { AppRoot } from "./app-root";
104
import "./app.css";
115

126
export default function App() {
137
return (
14-
<Router
15-
root={(props) => (
16-
<MetaProvider>
17-
<PreferencesProvider>
18-
<I18nProvider>
19-
<ThemeProvider>
20-
<Suspense>{props.children}</Suspense>
21-
22-
<Portal>
23-
<Toaster richColors />
24-
</Portal>
25-
</ThemeProvider>
26-
</I18nProvider>
27-
</PreferencesProvider>
28-
</MetaProvider>
29-
)}
30-
>
8+
<Router root={AppRoot}>
319
<FileRoutes />
3210
</Router>
3311
);

frontend/src/components/index.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
export * from "./ui";
2+
export * from "./session-expiration-monitor";

frontend/src/routes/(app).tsx renamed to frontend/src/components/session-expiration-monitor.tsx

Lines changed: 19 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,15 @@
1-
import { makeEventListener } from "@solid-primitives/event-listener";
2-
import { createAsync, revalidate, RouteDefinition, RouteSectionProps } from "@solidjs/router";
3-
import { createEffect, createSignal, on, onCleanup, onMount } from "solid-js";
1+
import { createAsync, revalidate } from "@solidjs/router";
2+
import { createEffect, createSignal, on, onCleanup, onMount, ParentComponent } from "solid-js";
3+
44
import { toast } from "solid-sonner";
5+
6+
import { makeEventListener } from "@solid-primitives/event-listener";
57
import { getCurrentUser } from "~/lib/api/users/me";
68
import { getIsLoggedIn, getSessionExpirationDate } from "~/lib/http";
79
import { useI18n } from "~/lib/i18n";
810

9-
export const route = {
10-
preload: () => {
11-
getIsLoggedIn();
12-
getSessionExpirationDate();
13-
},
14-
} satisfies RouteDefinition;
15-
16-
export default function Auth(props: RouteSectionProps) {
17-
const syncBroadcastChannel = new BroadcastChannel("auth_sync");
11+
export const SessionExpirationMonitor: ParentComponent = (props) => {
12+
const sync = new BroadcastChannel("auth_sync");
1813

1914
const i18n = useI18n();
2015

@@ -53,7 +48,7 @@ export default function Auth(props: RouteSectionProps) {
5348
};
5449

5550
onMount(() => {
56-
syncBroadcastChannel.onmessage = () => {
51+
sync.onmessage = () => {
5752
revalidateSession();
5853
};
5954
});
@@ -72,25 +67,21 @@ export default function Auth(props: RouteSectionProps) {
7267
);
7368

7469
createEffect(
75-
on(
76-
isLoggedIn,
77-
() => {
78-
syncBroadcastChannel.postMessage(true);
79-
80-
if (isLoggedIn() === false) {
81-
clearRevalidateTimeout();
82-
if (document.hidden) {
83-
makeEventListener(document, "visibilitychange", toastSessionExpired, { once: true });
84-
}
70+
on(isLoggedIn, () => {
71+
sync.postMessage(true);
72+
73+
if (isLoggedIn() === false && revalidateTimeout() !== undefined) {
74+
clearRevalidateTimeout();
75+
if (document.hidden) {
76+
makeEventListener(document, "visibilitychange", toastSessionExpired, { once: true });
8577
}
86-
},
87-
{ defer: true },
88-
),
78+
}
79+
}),
8980
);
9081

9182
onCleanup(() => {
92-
syncBroadcastChannel.close();
83+
sync.close();
9384
});
9485

9586
return props.children;
96-
}
87+
};

0 commit comments

Comments
 (0)