diff options
Diffstat (limited to 'subprojects/frontend/src')
-rw-r--r-- | subprojects/frontend/src/RegisterServiceWorker.tsx | 85 | ||||
-rw-r--r-- | subprojects/frontend/src/index.tsx | 19 |
2 files changed, 95 insertions, 9 deletions
diff --git a/subprojects/frontend/src/RegisterServiceWorker.tsx b/subprojects/frontend/src/RegisterServiceWorker.tsx new file mode 100644 index 00000000..c9b2e353 --- /dev/null +++ b/subprojects/frontend/src/RegisterServiceWorker.tsx | |||
@@ -0,0 +1,85 @@ | |||
1 | import Button from '@mui/material/Button'; | ||
2 | import { | ||
3 | type OptionsObject as SnackbarOptionsObject, | ||
4 | useSnackbar, | ||
5 | } from 'notistack'; | ||
6 | import React, { useEffect } from 'react'; | ||
7 | // eslint-disable-next-line import/no-unresolved -- Importing virtual module. | ||
8 | import { registerSW } from 'virtual:pwa-register'; | ||
9 | |||
10 | import { ContrastThemeProvider } from './theme/ThemeProvider'; | ||
11 | import getLogger from './utils/getLogger'; | ||
12 | |||
13 | const log = getLogger('RegisterServiceWorker'); | ||
14 | |||
15 | function UpdateSnackbarActions({ | ||
16 | closeCurrentSnackbar, | ||
17 | enqueueSnackbar, | ||
18 | updateSW, | ||
19 | }: { | ||
20 | closeCurrentSnackbar: () => void; | ||
21 | enqueueSnackbar: ( | ||
22 | message: string, | ||
23 | options?: SnackbarOptionsObject | undefined, | ||
24 | ) => void; | ||
25 | updateSW: (reloadPage: boolean) => Promise<void>; | ||
26 | }): JSX.Element { | ||
27 | return ( | ||
28 | <ContrastThemeProvider> | ||
29 | <Button | ||
30 | color="primary" | ||
31 | onClick={() => { | ||
32 | closeCurrentSnackbar(); | ||
33 | updateSW(true).catch((error) => { | ||
34 | log.error('Failed to update service worker', error); | ||
35 | enqueueSnackbar('Failed to download update', { | ||
36 | variant: 'error', | ||
37 | }); | ||
38 | }); | ||
39 | }} | ||
40 | > | ||
41 | Reload | ||
42 | </Button> | ||
43 | <Button color="inherit" onClick={closeCurrentSnackbar}> | ||
44 | Dismiss | ||
45 | </Button> | ||
46 | </ContrastThemeProvider> | ||
47 | ); | ||
48 | } | ||
49 | |||
50 | export default function RegisterServiceWorker(): null { | ||
51 | const { enqueueSnackbar, closeSnackbar } = useSnackbar(); | ||
52 | useEffect(() => { | ||
53 | if (import.meta.env.DEV) { | ||
54 | return; | ||
55 | } | ||
56 | if (!('serviceWorker' in navigator)) { | ||
57 | log.debug('No service worker support found'); | ||
58 | return; | ||
59 | } | ||
60 | const updateSW = registerSW({ | ||
61 | onNeedRefresh() { | ||
62 | const key = enqueueSnackbar('An update for Refinery is available', { | ||
63 | persist: true, | ||
64 | action: ( | ||
65 | <UpdateSnackbarActions | ||
66 | closeCurrentSnackbar={() => closeSnackbar(key)} | ||
67 | enqueueSnackbar={enqueueSnackbar} | ||
68 | updateSW={updateSW} | ||
69 | /> | ||
70 | ), | ||
71 | }); | ||
72 | }, | ||
73 | onOfflineReady() { | ||
74 | log.debug('Service worker is ready for offline use'); | ||
75 | }, | ||
76 | onRegistered() { | ||
77 | log.debug('Registered service worker'); | ||
78 | }, | ||
79 | onRegisterError(error) { | ||
80 | log.error('Failed to register service worker', error); | ||
81 | }, | ||
82 | }); | ||
83 | }, [enqueueSnackbar, closeSnackbar]); | ||
84 | return null; | ||
85 | } | ||
diff --git a/subprojects/frontend/src/index.tsx b/subprojects/frontend/src/index.tsx index 2176b277..b108df6d 100644 --- a/subprojects/frontend/src/index.tsx +++ b/subprojects/frontend/src/index.tsx | |||
@@ -1,6 +1,4 @@ | |||
1 | import CssBaseline from '@mui/material/CssBaseline'; | 1 | import CssBaseline from '@mui/material/CssBaseline'; |
2 | import React, { Suspense, lazy } from 'react'; | ||
3 | import { createRoot } from 'react-dom/client'; | ||
4 | import '@fontsource/jetbrains-mono/400.css'; | 2 | import '@fontsource/jetbrains-mono/400.css'; |
5 | import '@fontsource/jetbrains-mono/400-italic.css'; | 3 | import '@fontsource/jetbrains-mono/400-italic.css'; |
6 | import '@fontsource/jetbrains-mono/700.css'; | 4 | import '@fontsource/jetbrains-mono/700.css'; |
@@ -8,15 +6,15 @@ import '@fontsource/jetbrains-mono/700-italic.css'; | |||
8 | import '@fontsource/jetbrains-mono/variable.css'; | 6 | import '@fontsource/jetbrains-mono/variable.css'; |
9 | import '@fontsource/jetbrains-mono/variable-italic.css'; | 7 | import '@fontsource/jetbrains-mono/variable-italic.css'; |
10 | import '@fontsource/roboto/300.css'; | 8 | import '@fontsource/roboto/300.css'; |
11 | import '@fontsource/roboto/300-italic.css'; | ||
12 | import '@fontsource/roboto/400.css'; | 9 | import '@fontsource/roboto/400.css'; |
13 | import '@fontsource/roboto/400-italic.css'; | ||
14 | import '@fontsource/roboto/500.css'; | 10 | import '@fontsource/roboto/500.css'; |
15 | import '@fontsource/roboto/500-italic.css'; | ||
16 | import '@fontsource/roboto/700.css'; | 11 | import '@fontsource/roboto/700.css'; |
17 | import '@fontsource/roboto/700-italic.css'; | 12 | import { SnackbarProvider } from 'notistack'; |
13 | import React, { Suspense, lazy } from 'react'; | ||
14 | import { createRoot } from 'react-dom/client'; | ||
18 | 15 | ||
19 | import Loading from './Loading'; | 16 | import Loading from './Loading'; |
17 | import RegisterServiceWorker from './RegisterServiceWorker'; | ||
20 | import RootStore, { RootStoreProvider } from './RootStore'; | 18 | import RootStore, { RootStoreProvider } from './RootStore'; |
21 | import ThemeProvider from './theme/ThemeProvider'; | 19 | import ThemeProvider from './theme/ThemeProvider'; |
22 | import getLogger from './utils/getLogger'; | 20 | import getLogger from './utils/getLogger'; |
@@ -79,9 +77,12 @@ const app = ( | |||
79 | <RootStoreProvider rootStore={rootStore}> | 77 | <RootStoreProvider rootStore={rootStore}> |
80 | <ThemeProvider> | 78 | <ThemeProvider> |
81 | <CssBaseline enableColorScheme /> | 79 | <CssBaseline enableColorScheme /> |
82 | <Suspense fallback={<Loading />}> | 80 | <SnackbarProvider> |
83 | <App /> | 81 | <RegisterServiceWorker /> |
84 | </Suspense> | 82 | <Suspense fallback={<Loading />}> |
83 | <App /> | ||
84 | </Suspense> | ||
85 | </SnackbarProvider> | ||
85 | </ThemeProvider> | 86 | </ThemeProvider> |
86 | </RootStoreProvider> | 87 | </RootStoreProvider> |
87 | </React.StrictMode> | 88 | </React.StrictMode> |