Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 | import React, { useCallback, useEffect, useRef, useState } from "react"; import GlobalError from "components/error/GlobalError"; import AppToolbar from "./AppToolbar"; import BackgroundsPage from "components/pages/BackgroundsPage"; import SpritesPage from "components/pages/SpritesPage"; import DialoguePage from "components/pages/DialoguePage"; import WorldPage from "components/pages/WorldPage"; import MusicPage from "components/pages/MusicPage"; import PalettePage from "components/pages/PalettePage"; import SettingsPage from "components/pages/SettingsPage"; import { DropZone } from "ui/upload/DropZone"; import projectActions from "store/features/project/projectActions"; import SoundsPage from "components/pages/SoundsPage"; import LoadingPane from "ui/loading/LoadingPane"; import styled from "styled-components"; import { useAppDispatch, useAppSelector } from "store/hooks"; const AppWrapper = styled.div` width: 100%; height: 100%; display: flex; flex-direction: column; `; const AppContent = styled.div` width: 100%; height: calc(100% - 38px); display: flex; flex-direction: row; `; const App = () => { const dispatch = useAppDispatch(); const [draggingOver, setDraggingOver] = useState(false); const dragLeaveTimer = useRef<ReturnType<typeof setTimeout>>(); const section = useAppSelector((state) => state.navigation.section); const error = useAppSelector((state) => state.error); const loaded = useAppSelector((state) => state.document.loaded); const onDragOver = useCallback( (e: DragEvent) => { // Don't activate dropzone unless dragging a file const types = e.dataTransfer?.types; Iif (!types || types.indexOf("Files") === -1) { return; } e.preventDefault(); e.stopPropagation(); Iif (dragLeaveTimer.current) { clearTimeout(dragLeaveTimer.current); } Iif (!draggingOver) { setDraggingOver(true); } }, [draggingOver] ); const onDragLeave = useCallback((e: DragEvent) => { e.preventDefault(); e.stopPropagation(); Iif (dragLeaveTimer.current) { clearTimeout(dragLeaveTimer.current); } dragLeaveTimer.current = setTimeout(() => { setDraggingOver(false); }, 100); }, []); const onDrop = useCallback( (e: DragEvent) => { setDraggingOver(false); Iif (!e.dataTransfer?.files) { return; } for (let i = 0; i < e.dataTransfer.files.length; i++) { const file = e.dataTransfer.files[i]; dispatch(projectActions.addFileToProject(file.path)); } }, [dispatch] ); useEffect(() => { window.addEventListener("dragover", onDragOver); window.addEventListener("dragleave", onDragLeave); window.addEventListener("drop", onDrop); return () => { window.removeEventListener("dragover", onDragOver); window.removeEventListener("dragleave", onDragLeave); window.removeEventListener("drop", onDrop); }; }, [onDragLeave, onDragOver, onDrop]); Iif (error.visible) { return <GlobalError />; } return ( <AppWrapper> <AppToolbar /> {!loaded ? ( <LoadingPane /> ) : ( <AppContent> {section === "world" && <WorldPage />} {section === "backgrounds" && <BackgroundsPage />} {section === "sprites" && <SpritesPage />} {section === "music" && <MusicPage />} {section === "sounds" && <SoundsPage />} {section === "palettes" && <PalettePage />} {section === "dialogue" && <DialoguePage />} {section === "settings" && <SettingsPage />} {draggingOver && <DropZone />} </AppContent> )} </AppWrapper> ); }; export default App; |