diff options
Diffstat (limited to 'subprojects/frontend/src/editor/AnalysisErrorNotification.tsx')
-rw-r--r-- | subprojects/frontend/src/editor/AnalysisErrorNotification.tsx | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/subprojects/frontend/src/editor/AnalysisErrorNotification.tsx b/subprojects/frontend/src/editor/AnalysisErrorNotification.tsx new file mode 100644 index 00000000..591a3600 --- /dev/null +++ b/subprojects/frontend/src/editor/AnalysisErrorNotification.tsx | |||
@@ -0,0 +1,74 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | |||
7 | import { reaction } from 'mobx'; | ||
8 | import { type SnackbarKey, useSnackbar } from 'notistack'; | ||
9 | import { useEffect, useState } from 'react'; | ||
10 | |||
11 | import type EditorStore from './EditorStore'; | ||
12 | |||
13 | function MessageObserver({ | ||
14 | editorStore, | ||
15 | }: { | ||
16 | editorStore: EditorStore; | ||
17 | }): React.ReactNode { | ||
18 | const [message, setMessage] = useState( | ||
19 | editorStore.delayedErrors.semanticsError ?? '', | ||
20 | ); | ||
21 | // Instead of making this component an `observer`, | ||
22 | // we only update the message is one is present to make sure that the | ||
23 | // disappear animation has a chance to complete. | ||
24 | useEffect( | ||
25 | () => | ||
26 | reaction( | ||
27 | () => editorStore.delayedErrors.semanticsError, | ||
28 | (newMessage) => { | ||
29 | if (newMessage !== undefined) { | ||
30 | setMessage(newMessage); | ||
31 | } | ||
32 | }, | ||
33 | { fireImmediately: false }, | ||
34 | ), | ||
35 | [editorStore], | ||
36 | ); | ||
37 | return message; | ||
38 | } | ||
39 | |||
40 | export default function AnalysisErrorNotification({ | ||
41 | editorStore, | ||
42 | }: { | ||
43 | editorStore: EditorStore; | ||
44 | }): null { | ||
45 | const { enqueueSnackbar, closeSnackbar } = useSnackbar(); | ||
46 | useEffect(() => { | ||
47 | let key: SnackbarKey | undefined; | ||
48 | const disposer = reaction( | ||
49 | () => editorStore.delayedErrors.semanticsError !== undefined, | ||
50 | (hasError) => { | ||
51 | if (hasError) { | ||
52 | if (key === undefined) { | ||
53 | key = enqueueSnackbar({ | ||
54 | message: <MessageObserver editorStore={editorStore} />, | ||
55 | variant: 'error', | ||
56 | persist: true, | ||
57 | }); | ||
58 | } | ||
59 | } else if (key !== undefined) { | ||
60 | closeSnackbar(key); | ||
61 | key = undefined; | ||
62 | } | ||
63 | }, | ||
64 | { fireImmediately: true }, | ||
65 | ); | ||
66 | return () => { | ||
67 | disposer(); | ||
68 | if (key !== undefined) { | ||
69 | closeSnackbar(key); | ||
70 | } | ||
71 | }; | ||
72 | }, [editorStore, enqueueSnackbar, closeSnackbar]); | ||
73 | return null; | ||
74 | } | ||