2022-01-09 17:15:09 +01:00
|
|
|
import React, { useState, useEffect, useRef } from "react";
|
|
|
|
import Draggable, { DraggableEventHandler } from "react-draggable";
|
2021-09-19 06:46:39 +02:00
|
|
|
import makeStyles from "@mui/styles/makeStyles";
|
|
|
|
import Collapse from "@mui/material/Collapse";
|
2021-10-18 09:14:33 +02:00
|
|
|
import Paper from "@mui/material/Paper";
|
2022-01-09 17:15:09 +01:00
|
|
|
import KeyboardArrowDownIcon from "@mui/icons-material/KeyboardArrowDown";
|
|
|
|
import KeyboardArrowUpIcon from "@mui/icons-material/KeyboardArrowUp";
|
|
|
|
import EqualizerIcon from "@mui/icons-material/Equalizer";
|
|
|
|
import SchoolIcon from "@mui/icons-material/School";
|
2021-09-19 23:05:27 +02:00
|
|
|
import { use } from "../Context";
|
|
|
|
import { Page } from "../Router";
|
2022-01-09 17:15:09 +01:00
|
|
|
import { Settings } from "../../Settings/Settings";
|
|
|
|
import { Box, Button, Typography } from "@mui/material";
|
|
|
|
import { debounce } from "lodash";
|
2021-09-19 06:46:39 +02:00
|
|
|
|
|
|
|
const useStyles = makeStyles({
|
2021-10-18 09:14:33 +02:00
|
|
|
overviewContainer: {
|
|
|
|
position: "fixed",
|
|
|
|
top: 0,
|
|
|
|
right: 0,
|
|
|
|
zIndex: 1500,
|
|
|
|
display: "flex",
|
|
|
|
justifyContent: "flex-end",
|
|
|
|
flexDirection: "column",
|
2021-09-19 06:46:39 +02:00
|
|
|
},
|
2022-01-09 17:15:09 +01:00
|
|
|
|
|
|
|
header: {
|
|
|
|
cursor: "grab",
|
|
|
|
textAlign: "center",
|
|
|
|
display: "flex",
|
|
|
|
flexDirection: "row",
|
|
|
|
alignItems: "center",
|
|
|
|
},
|
|
|
|
|
|
|
|
visibilityToggle: {
|
|
|
|
padding: "2px",
|
|
|
|
minWidth: "inherit",
|
|
|
|
backgroundColor: "transparent",
|
|
|
|
border: "none",
|
|
|
|
"&:hover": {
|
|
|
|
backgroundColor: "rgba(255, 255, 255, 0.1)",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
collapse: {
|
|
|
|
borderTop: `1px solid ${Settings.theme.welllight}`,
|
|
|
|
margin: "0 auto",
|
|
|
|
},
|
|
|
|
|
|
|
|
icon: {
|
|
|
|
fontSize: "24px",
|
|
|
|
},
|
2021-09-19 06:46:39 +02:00
|
|
|
});
|
|
|
|
|
|
|
|
interface IProps {
|
|
|
|
children: JSX.Element[] | JSX.Element | React.ReactElement[] | React.ReactElement;
|
2022-01-09 17:15:09 +01:00
|
|
|
mode: "tutorial" | "overview";
|
|
|
|
}
|
|
|
|
|
|
|
|
export interface OverviewSettings {
|
|
|
|
opened: boolean;
|
|
|
|
x: number;
|
|
|
|
y: number;
|
2021-09-19 06:46:39 +02:00
|
|
|
}
|
|
|
|
|
2022-01-09 17:15:09 +01:00
|
|
|
export function Overview({ children, mode }: IProps): React.ReactElement {
|
|
|
|
const draggableRef = useRef<HTMLDivElement>(null);
|
|
|
|
const [open, setOpen] = useState(Settings.overview.opened);
|
|
|
|
const [x, setX] = useState(Settings.overview.x);
|
|
|
|
const [y, setY] = useState(Settings.overview.y);
|
2021-09-19 06:46:39 +02:00
|
|
|
const classes = useStyles();
|
2021-09-19 23:05:27 +02:00
|
|
|
const router = use.Router();
|
2022-01-09 17:15:09 +01:00
|
|
|
|
|
|
|
const CurrentIcon = open ? KeyboardArrowUpIcon : KeyboardArrowDownIcon;
|
|
|
|
const LeftIcon = mode === "tutorial" ? SchoolIcon : EqualizerIcon;
|
|
|
|
const header = mode === "tutorial" ? "Tutorial" : "Overview";
|
|
|
|
const handleStop: DraggableEventHandler = (e, data) => {
|
|
|
|
setX(data.x);
|
|
|
|
setY(data.y);
|
|
|
|
};
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
Settings.overview = { x, y, opened: open };
|
|
|
|
}, [open, x, y]);
|
|
|
|
|
|
|
|
// Trigger fakeDrag once to make sure loaded data is not outside bounds
|
|
|
|
useEffect(() => fakeDrag(), []);
|
|
|
|
|
|
|
|
// And trigger fakeDrag when the window is resized
|
|
|
|
useEffect(() => {
|
|
|
|
window.addEventListener("resize", fakeDrag);
|
|
|
|
return () => {
|
|
|
|
window.removeEventListener("resize", fakeDrag);
|
|
|
|
};
|
|
|
|
}, []);
|
|
|
|
|
|
|
|
const fakeDrag = debounce((): void => {
|
|
|
|
const node = draggableRef?.current;
|
|
|
|
if (!node) return;
|
|
|
|
|
|
|
|
// No official way to trigger an onChange to recompute the bounds
|
|
|
|
// See: https://github.com/react-grid-layout/react-draggable/issues/363#issuecomment-947751127
|
|
|
|
triggerMouseEvent(node, "mouseover");
|
|
|
|
triggerMouseEvent(node, "mousedown");
|
|
|
|
triggerMouseEvent(document, "mousemove");
|
|
|
|
triggerMouseEvent(node, "mouseup");
|
|
|
|
triggerMouseEvent(node, "click");
|
|
|
|
}, 100);
|
|
|
|
|
|
|
|
const triggerMouseEvent = (node: HTMLDivElement | Document, eventType: string): void => {
|
|
|
|
const clickEvent = document.createEvent("MouseEvents");
|
|
|
|
clickEvent.initEvent(eventType, true, true);
|
|
|
|
node.dispatchEvent(clickEvent);
|
|
|
|
};
|
|
|
|
|
2021-11-02 22:28:19 +01:00
|
|
|
if (router.page() === Page.BitVerse || router.page() === Page.Loading || router.page() === Page.Recovery)
|
|
|
|
return <></>;
|
2021-09-19 06:46:39 +02:00
|
|
|
return (
|
2022-01-09 17:15:09 +01:00
|
|
|
<Draggable handle=".drag" bounds="body" onStop={handleStop} defaultPosition={{ x, y }}>
|
|
|
|
<Paper className={classes.overviewContainer} square>
|
|
|
|
<Box className="drag" onDoubleClick={() => setOpen((old) => !old)} ref={draggableRef}>
|
|
|
|
<Box className={classes.header}>
|
|
|
|
<LeftIcon color="secondary" className={classes.icon} sx={{ padding: "2px" }} />
|
|
|
|
<Typography flexGrow={1} color="secondary">
|
|
|
|
{header}
|
|
|
|
</Typography>
|
2022-01-20 22:11:48 +01:00
|
|
|
<Button
|
|
|
|
aria-label="expand or collapse character overview"
|
|
|
|
variant="text"
|
|
|
|
size="small"
|
|
|
|
className={classes.visibilityToggle}
|
|
|
|
>
|
2022-01-09 17:15:09 +01:00
|
|
|
{<CurrentIcon className={classes.icon} color="secondary" onClick={() => setOpen((old) => !old)} />}
|
|
|
|
</Button>
|
|
|
|
</Box>
|
|
|
|
</Box>
|
|
|
|
<Collapse in={open} className={classes.collapse}>
|
|
|
|
{children}
|
|
|
|
</Collapse>
|
|
|
|
</Paper>
|
|
|
|
</Draggable>
|
2021-09-19 06:46:39 +02:00
|
|
|
);
|
2021-11-02 22:28:19 +01:00
|
|
|
}
|