Refactor error banners and add new slimlined reconnect and offline banners
This commit is contained in:
parent
83d80fbbbd
commit
815cc3aead
@ -2,7 +2,13 @@ import React from "react";
|
|||||||
import Modal from "react-modal";
|
import Modal from "react-modal";
|
||||||
import { useThemeUI, Close } from "theme-ui";
|
import { useThemeUI, Close } from "theme-ui";
|
||||||
|
|
||||||
function Banner({ isOpen, onRequestClose, children, allowClose }) {
|
function Banner({
|
||||||
|
isOpen,
|
||||||
|
onRequestClose,
|
||||||
|
children,
|
||||||
|
allowClose,
|
||||||
|
backgroundColor,
|
||||||
|
}) {
|
||||||
const { theme } = useThemeUI();
|
const { theme } = useThemeUI();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -12,7 +18,7 @@ function Banner({ isOpen, onRequestClose, children, allowClose }) {
|
|||||||
style={{
|
style={{
|
||||||
overlay: { bottom: "0", top: "initial", zIndex: 2000 },
|
overlay: { bottom: "0", top: "initial", zIndex: 2000 },
|
||||||
content: {
|
content: {
|
||||||
backgroundColor: theme.colors.highlight,
|
backgroundColor: backgroundColor || theme.colors.highlight,
|
||||||
color: "hsl(210, 50%, 96%)",
|
color: "hsl(210, 50%, 96%)",
|
||||||
top: "initial",
|
top: "initial",
|
||||||
left: "50%",
|
left: "50%",
|
||||||
@ -22,7 +28,7 @@ function Banner({ isOpen, onRequestClose, children, allowClose }) {
|
|||||||
border: "none",
|
border: "none",
|
||||||
padding: "8px",
|
padding: "8px",
|
||||||
margin: "8px",
|
margin: "8px",
|
||||||
paddingRight: "24px",
|
paddingRight: allowClose ? "24px" : "8px",
|
||||||
maxWidth: "500px",
|
maxWidth: "500px",
|
||||||
transform: "translateX(-50%)",
|
transform: "translateX(-50%)",
|
||||||
},
|
},
|
18
src/components/banner/ErrorBanner.js
Normal file
18
src/components/banner/ErrorBanner.js
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { Box, Text } from "theme-ui";
|
||||||
|
|
||||||
|
import Banner from "./Banner";
|
||||||
|
|
||||||
|
function ErrorBanner({ error, onRequestClose }) {
|
||||||
|
return (
|
||||||
|
<Banner isOpen={!!error} onRequestClose={onRequestClose}>
|
||||||
|
<Box p={1}>
|
||||||
|
<Text as="p" variant="body2">
|
||||||
|
Error: {error && error.message}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
</Banner>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ErrorBanner;
|
33
src/components/banner/OfflineBanner.js
Normal file
33
src/components/banner/OfflineBanner.js
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { Flex } from "theme-ui";
|
||||||
|
|
||||||
|
import Banner from "./Banner";
|
||||||
|
import OfflineIcon from "../../icons/OfflineIcon";
|
||||||
|
|
||||||
|
function OfflineBanner({ isOpen }) {
|
||||||
|
return (
|
||||||
|
<Banner
|
||||||
|
isOpen={isOpen}
|
||||||
|
onRequestClose={() => {}}
|
||||||
|
allowClose={false}
|
||||||
|
backgroundColor="transparent"
|
||||||
|
>
|
||||||
|
<Flex
|
||||||
|
sx={{
|
||||||
|
width: "28px",
|
||||||
|
height: "28px",
|
||||||
|
borderRadius: "28px",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center",
|
||||||
|
}}
|
||||||
|
bg="overlay"
|
||||||
|
title="Unable to connect to game, refresh to reconnect."
|
||||||
|
aria-label="Unable to connect to game, refresh to reconnect."
|
||||||
|
>
|
||||||
|
<OfflineIcon />
|
||||||
|
</Flex>
|
||||||
|
</Banner>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default OfflineBanner;
|
33
src/components/banner/ReconnectBanner.js
Normal file
33
src/components/banner/ReconnectBanner.js
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { Flex } from "theme-ui";
|
||||||
|
|
||||||
|
import Banner from "./Banner";
|
||||||
|
import ReconnectingIcon from "../../icons/ReconnectingIcon";
|
||||||
|
|
||||||
|
function ReconnectBanner({ isOpen }) {
|
||||||
|
return (
|
||||||
|
<Banner
|
||||||
|
isOpen={isOpen}
|
||||||
|
onRequestClose={() => {}}
|
||||||
|
allowClose={false}
|
||||||
|
backgroundColor="transparent"
|
||||||
|
>
|
||||||
|
<Flex
|
||||||
|
sx={{
|
||||||
|
width: "28px",
|
||||||
|
height: "28px",
|
||||||
|
borderRadius: "28px",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center",
|
||||||
|
}}
|
||||||
|
bg="overlay"
|
||||||
|
title="Disconnected. Attempting to reconnect..."
|
||||||
|
aria-label="Disconnected. Attempting to reconnect..."
|
||||||
|
>
|
||||||
|
<ReconnectingIcon />
|
||||||
|
</Flex>
|
||||||
|
</Banner>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ReconnectBanner;
|
@ -1,5 +1,4 @@
|
|||||||
import React, { useRef, useEffect, useState } from "react";
|
import React, { useRef, useEffect, useState } from "react";
|
||||||
import { Box, Text } from "theme-ui";
|
|
||||||
import { Engine } from "@babylonjs/core/Engines/engine";
|
import { Engine } from "@babylonjs/core/Engines/engine";
|
||||||
import { Scene } from "@babylonjs/core/scene";
|
import { Scene } from "@babylonjs/core/scene";
|
||||||
import { Vector3, Color4, Matrix } from "@babylonjs/core/Maths/math";
|
import { Vector3, Color4, Matrix } from "@babylonjs/core/Maths/math";
|
||||||
@ -19,7 +18,7 @@ import ReactResizeDetector from "react-resize-detector";
|
|||||||
|
|
||||||
import usePreventTouch from "../../hooks/usePreventTouch";
|
import usePreventTouch from "../../hooks/usePreventTouch";
|
||||||
|
|
||||||
import Banner from "../Banner";
|
import ErrorBanner from "../banner/ErrorBanner";
|
||||||
|
|
||||||
const diceThrowSpeed = 2;
|
const diceThrowSpeed = 2;
|
||||||
|
|
||||||
@ -166,13 +165,7 @@ function DiceInteraction({ onSceneMount, onPointerDown, onPointerUp }) {
|
|||||||
style={{ outline: "none" }}
|
style={{ outline: "none" }}
|
||||||
/>
|
/>
|
||||||
</ReactResizeDetector>
|
</ReactResizeDetector>
|
||||||
<Banner isOpen={!!error} onRequestClose={() => setError()}>
|
<ErrorBanner error={error} onRequestClose={() => setError()} />
|
||||||
<Box p={1}>
|
|
||||||
<Text as="p" variant="body2">
|
|
||||||
Error: {error && error.message}
|
|
||||||
</Text>
|
|
||||||
</Box>
|
|
||||||
</Banner>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@ import { Text, IconButton, Box, Flex } from "theme-ui";
|
|||||||
|
|
||||||
import StreamMuteIcon from "../../icons/StreamMuteIcon";
|
import StreamMuteIcon from "../../icons/StreamMuteIcon";
|
||||||
|
|
||||||
import Banner from "../Banner";
|
import Banner from "../banner/Banner";
|
||||||
import Slider from "../Slider";
|
import Slider from "../Slider";
|
||||||
|
|
||||||
function Stream({ stream, nickname }) {
|
function Stream({ stream, nickname }) {
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import React, { useState, useEffect, useContext } from "react";
|
import React, { useState, useEffect, useContext } from "react";
|
||||||
import { Box, Text } from "theme-ui";
|
|
||||||
|
|
||||||
import Banner from "../components/Banner";
|
import ErrorBanner from "../components/banner/ErrorBanner";
|
||||||
|
|
||||||
import { getDatabase } from "../database";
|
import { getDatabase } from "../database";
|
||||||
|
|
||||||
@ -64,16 +63,10 @@ export function DatabaseProvider({ children }) {
|
|||||||
<DatabaseContext.Provider value={value}>
|
<DatabaseContext.Provider value={value}>
|
||||||
<>
|
<>
|
||||||
{children}
|
{children}
|
||||||
<Banner
|
<ErrorBanner
|
||||||
isOpen={!!databaseError}
|
error={databaseError}
|
||||||
onRequestClose={() => setDatabaseError()}
|
onRequestClose={() => setDatabaseError()}
|
||||||
>
|
/>
|
||||||
<Box p={1}>
|
|
||||||
<Text as="p" variant="body2">
|
|
||||||
{databaseError && databaseError.message}
|
|
||||||
</Text>
|
|
||||||
</Box>
|
|
||||||
</Banner>
|
|
||||||
</>
|
</>
|
||||||
</DatabaseContext.Provider>
|
</DatabaseContext.Provider>
|
||||||
);
|
);
|
||||||
|
18
src/icons/OfflineIcon.js
Normal file
18
src/icons/OfflineIcon.js
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import React from "react";
|
||||||
|
|
||||||
|
function PointerToolIcon() {
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
width="24"
|
||||||
|
fill="currentcolor"
|
||||||
|
>
|
||||||
|
<path d="M0 0h24v24H0V0zm0 0h24v24H0V0z" fill="none" />
|
||||||
|
<path d="M10 5.74v-.19c0-.68-.71-1.11-1.32-.82-.19.09-.36.2-.54.3L9.6 6.49c.24-.18.4-.45.4-.75zM20 12c0-2.21-.91-4.2-2.36-5.64l1.51-1.51c.31-.31.09-.85-.36-.85H14v4.79c0 .45.54.67.85.35l1.39-1.39C17.32 8.85 18 10.34 18 12c0 .85-.18 1.66-.5 2.39l1.48 1.48C19.62 14.72 20 13.41 20 12zM3.57 4.7c-.39.39-.39 1.02 0 1.41l1.65 1.65C4.45 9 4 10.44 4 12c0 2.21.91 4.2 2.36 5.64l-1.51 1.51c-.31.31-.09.85.36.85H9.5c.28 0 .5-.22.5-.5v-4.29c0-.45-.54-.67-.85-.35l-1.39 1.39C6.68 15.15 6 13.66 6 12c0-1 .26-1.93.69-2.76l8.07 8.07c-.01.02-.01.02-.01.04-.43.12-.75.48-.75.91v.18c0 .68.71 1.11 1.32.82.31-.14.61-.31.9-.49l1.87 1.87c.39.39 1.02.39 1.41 0 .39-.39.39-1.02 0-1.41L4.98 4.7c-.39-.39-1.02-.39-1.41 0z" />
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PointerToolIcon;
|
28
src/icons/ReconnectingIcon.js
Normal file
28
src/icons/ReconnectingIcon.js
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import React from "react";
|
||||||
|
|
||||||
|
function ReconnectingIcon() {
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
width="24"
|
||||||
|
fill="currentcolor"
|
||||||
|
>
|
||||||
|
<path d="M.01 0h24v24h-24V0z" fill="none" />
|
||||||
|
<path d="M12 4V2.21c0-.45-.54-.67-.85-.35l-2.8 2.79c-.2.2-.2.51 0 .71l2.79 2.79c.32.31.86.09.86-.36V6c3.31 0 6 2.69 6 6 0 .79-.15 1.56-.44 2.25-.15.36-.04.77.23 1.04.51.51 1.37.33 1.64-.34.37-.91.57-1.91.57-2.95 0-4.42-3.58-8-8-8zm0 14c-3.31 0-6-2.69-6-6 0-.79.15-1.56.44-2.25.15-.36.04-.77-.23-1.04-.51-.51-1.37-.33-1.64.34C4.2 9.96 4 10.96 4 12c0 4.42 3.58 8 8 8v1.79c0 .45.54.67.85.35l2.79-2.79c.2-.2.2-.51 0-.71l-2.79-2.79c-.31-.31-.85-.09-.85.36V18z">
|
||||||
|
<animateTransform
|
||||||
|
attributeName="transform"
|
||||||
|
attributeType="XML"
|
||||||
|
type="rotate"
|
||||||
|
from="360 12 12"
|
||||||
|
to="0 12 12"
|
||||||
|
dur="2s"
|
||||||
|
repeatCount="indefinite"
|
||||||
|
/>
|
||||||
|
</path>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ReconnectingIcon;
|
@ -8,7 +8,7 @@ import { useToasts } from "react-toast-notifications";
|
|||||||
import Modal from "../components/Modal";
|
import Modal from "../components/Modal";
|
||||||
import LoadingOverlay from "../components/LoadingOverlay";
|
import LoadingOverlay from "../components/LoadingOverlay";
|
||||||
import LoadingBar from "../components/LoadingBar";
|
import LoadingBar from "../components/LoadingBar";
|
||||||
import Banner from "../components/Banner";
|
import ErrorBanner from "../components/banner/ErrorBanner";
|
||||||
|
|
||||||
import { useAuth } from "../contexts/AuthContext";
|
import { useAuth } from "../contexts/AuthContext";
|
||||||
|
|
||||||
@ -271,13 +271,7 @@ function ImportExportModal({ isOpen, onRequestClose }) {
|
|||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
<Banner isOpen={!!error} onRequestClose={() => setError()}>
|
<ErrorBanner error={error} onRequestClose={() => setError()} />
|
||||||
<Box p={1}>
|
|
||||||
<Text as="p" variant="body2">
|
|
||||||
Error: {error && error.message}
|
|
||||||
</Text>
|
|
||||||
</Box>
|
|
||||||
</Banner>
|
|
||||||
<SelectDataModal
|
<SelectDataModal
|
||||||
isOpen={showImportSelector}
|
isOpen={showImportSelector}
|
||||||
onRequestClose={handleImportSelectorClose}
|
onRequestClose={handleImportSelectorClose}
|
||||||
|
@ -12,7 +12,7 @@ import {
|
|||||||
import { useLocation } from "react-router-dom";
|
import { useLocation } from "react-router-dom";
|
||||||
|
|
||||||
import Footer from "../components/Footer";
|
import Footer from "../components/Footer";
|
||||||
import Banner from "../components/Banner";
|
import ErrorBanner from "../components/banner/ErrorBanner";
|
||||||
import LoadingOverlay from "../components/LoadingOverlay";
|
import LoadingOverlay from "../components/LoadingOverlay";
|
||||||
|
|
||||||
import { logError } from "../helpers/logging";
|
import { logError } from "../helpers/logging";
|
||||||
@ -159,13 +159,7 @@ function Donate() {
|
|||||||
</Flex>
|
</Flex>
|
||||||
<Footer />
|
<Footer />
|
||||||
{loading && <LoadingOverlay />}
|
{loading && <LoadingOverlay />}
|
||||||
<Banner isOpen={!!error} onRequestClose={() => setError(null)}>
|
<ErrorBanner error={error} onRequestClose={() => setError()} />
|
||||||
<Box p={1}>
|
|
||||||
<Text as="p" variant="body2">
|
|
||||||
{error}
|
|
||||||
</Text>
|
|
||||||
</Box>
|
|
||||||
</Banner>
|
|
||||||
</Flex>
|
</Flex>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,9 @@ import React, { useState, useEffect, useRef } from "react";
|
|||||||
import { Flex, Box, Text } from "theme-ui";
|
import { Flex, Box, Text } from "theme-ui";
|
||||||
import { useParams } from "react-router-dom";
|
import { useParams } from "react-router-dom";
|
||||||
|
|
||||||
import Banner from "../components/Banner";
|
import Banner from "../components/banner/Banner";
|
||||||
|
import ReconnectBanner from "../components/banner/ReconnectBanner";
|
||||||
|
import OfflineBanner from "../components/banner/OfflineBanner";
|
||||||
import LoadingOverlay from "../components/LoadingOverlay";
|
import LoadingOverlay from "../components/LoadingOverlay";
|
||||||
import Link from "../components/Link";
|
import Link from "../components/Link";
|
||||||
import MapLoadingOverlay from "../components/map/MapLoadingOverlay";
|
import MapLoadingOverlay from "../components/map/MapLoadingOverlay";
|
||||||
@ -125,28 +127,8 @@ function Game() {
|
|||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
</Banner>
|
</Banner>
|
||||||
<Banner
|
<OfflineBanner isOpen={sessionStatus === "offline"} />
|
||||||
isOpen={sessionStatus === "offline"}
|
<ReconnectBanner isOpen={sessionStatus === "reconnecting"} />
|
||||||
onRequestClose={() => {}}
|
|
||||||
allowClose={false}
|
|
||||||
>
|
|
||||||
<Box p={1}>
|
|
||||||
<Text as="p" variant="body2">
|
|
||||||
Unable to connect to game, refresh to reconnect.
|
|
||||||
</Text>
|
|
||||||
</Box>
|
|
||||||
</Banner>
|
|
||||||
<Banner
|
|
||||||
isOpen={sessionStatus === "reconnecting"}
|
|
||||||
onRequestClose={() => {}}
|
|
||||||
allowClose={false}
|
|
||||||
>
|
|
||||||
<Box p={1}>
|
|
||||||
<Text as="p" variant="body2">
|
|
||||||
Disconnected. Attempting to reconnect...
|
|
||||||
</Text>
|
|
||||||
</Box>
|
|
||||||
</Banner>
|
|
||||||
<AuthModal
|
<AuthModal
|
||||||
isOpen={sessionStatus === "auth"}
|
isOpen={sessionStatus === "auth"}
|
||||||
onSubmit={handleAuthSubmit}
|
onSubmit={handleAuthSubmit}
|
||||||
|
Loading…
Reference in New Issue
Block a user