Line data Source code
1 : import * as React from 'react';
2 : import * as styles from './file_dropzone.module.css';
3 :
4 : import { DRAG_EVENT, DRAG_STOP_EVENT, DROP_EVENT, PlatformDragDropEventVariant } from '../platform/events/event.js';
5 : import { PlatformFile } from '../platform/file/file.js';
6 : import { usePlatformEventListener } from '../platform/events/event_listener_provider.js';
7 : import { FileLoader } from './file_loader.js';
8 : import { FlavorLogo } from '../config/flavor_provider.js';
9 :
10 0 : function FileDropzoneArea() {
11 0 : return (
12 0 : <div className={styles.area_centered}>
13 0 : <div className={styles.area_container}>
14 0 : <div className={styles.area_logo}>
15 0 : <FlavorLogo width={180} />
16 0 : </div>
17 0 : </div>
18 0 : </div>
19 : );
20 0 : }
21 :
22 1 : export function FileDropzone(props: { children: React.ReactElement }) {
23 1 : const appEvents = usePlatformEventListener();
24 1 : const [droppedFile, setDroppedFile] = React.useState<PlatformFile | null>(null);
25 1 : const [dragOngoing, setDragOngoing] = React.useState<Date | null>(null);
26 :
27 : // Callback to drop file
28 1 : const onDropFile = React.useCallback(async (file: PlatformFile) => setDroppedFile(file), []);
29 : // Callback for drag/drop events
30 1 : const onDragDrop = React.useCallback((event: PlatformDragDropEventVariant) => {
31 0 : switch (event.type) {
32 0 : case DRAG_EVENT:
33 0 : setDragOngoing(new Date());
34 0 : break;
35 0 : case DRAG_STOP_EVENT:
36 0 : setDragOngoing(null);
37 0 : break;
38 0 : case DROP_EVENT: {
39 0 : onDropFile(event.value.file);
40 0 : setDragOngoing(null);
41 : break;
42 : }
43 0 : }
44 1 : }, []);
45 :
46 : // Subscribe drag/drop events
47 1 : React.useEffect(() => {
48 1 : appEvents.subscribeDragDropEvents("dropzone", onDragDrop);
49 1 : return () => appEvents.unsubscribeDragDropEvents("dropzone");
50 1 : }, [appEvents, onDragDrop]);
51 :
52 : // On-done handler to close the dropzone again
53 1 : const closeDropzone = React.useCallback(() => {
54 0 : setDroppedFile(null);
55 1 : }, []);
56 :
57 : // Determine content
58 1 : let content: React.ReactElement = props.children;
59 1 : if (droppedFile != null) {
60 1 : content = <FileLoader file={droppedFile} onDone={closeDropzone} />;
61 1 : } else if (dragOngoing) {
62 1 : content = <FileDropzoneArea />;
63 : }
64 1 : return (
65 1 : <div className={styles.root}>
66 1 : {content}
67 1 : </div>
68 : );
69 1 : }
|