Added progress indicator to map data loading

This commit is contained in:
Mitchell McCaffrey 2020-06-28 12:28:58 +10:00
parent a370b8e11d
commit bf022e2686
6 changed files with 63 additions and 9 deletions

View File

@ -1,9 +1,9 @@
import React from "react";
import { Box } from "theme-ui";
import { Box, Progress } from "theme-ui";
import Spinner from "./Spinner";
function LoadingOverlay() {
function LoadingOverlay({ progress }) {
return (
<Box
sx={{
@ -15,10 +15,14 @@ function LoadingOverlay() {
alignItems: "center",
top: 0,
left: 0,
flexDirection: "column",
}}
bg="muted"
>
<Spinner />
{progress && (
<Progress max={1} value={progress} m={2} sx={{ width: "24px" }} />
)}
</Box>
);
}

View File

@ -36,7 +36,7 @@ function Map({
disabledTokens,
}) {
const { tokensById } = useContext(TokenDataContext);
const { isLoading } = useContext(MapLoadingContext);
const { isLoading, loadingProgress } = useContext(MapLoadingContext);
const gridX = map && map.gridX;
const gridY = map && map.gridY;
@ -299,7 +299,7 @@ function Map({
{tokenMenu}
{tokenDragOverlay}
<MapDice />
{isLoading && <LoadingOverlay />}
{isLoading && <LoadingOverlay progress={loadingProgress} />}
</>
}
selectedToolId={selectedToolId}

View File

@ -1,4 +1,5 @@
import React, { useState } from "react";
import { omit, isEmpty } from "../helpers/shared";
const MapLoadingContext = React.createContext();
@ -13,12 +14,36 @@ export function MapLoadingProvider({ children }) {
setLoadingAssetCount((prevLoadingAssets) => prevLoadingAssets - 1);
}
const [assetProgress, setAssetProgress] = useState({});
function assetProgressUpdate({ id, count, total }) {
if (count === total) {
setAssetProgress(omit(assetProgress, [id]));
} else {
setAssetProgress((prevAssetProgress) => ({
...prevAssetProgress,
[id]: { count, total },
}));
}
}
const isLoading = loadingAssetCount > 0;
let loadingProgress = null;
if (!isEmpty(assetProgress)) {
let total = 0;
let count = 0;
for (let progress of Object.values(assetProgress)) {
total += progress.total;
count += progress.count;
}
loadingProgress = count / total;
}
const value = {
assetLoadStart,
assetLoadFinish,
isLoading,
assetProgressUpdate,
loadingProgress,
};
return (

View File

@ -29,6 +29,12 @@ class Peer extends SimplePeer {
chunk.count++;
this.currentChunks[unpacked.id] = chunk;
this.emit("dataProgress", {
id: unpacked.id,
count: chunk.count,
total: chunk.total,
});
// All chunks have been loaded
if (chunk.count === chunk.total) {
// Merge chunks with a blob

View File

@ -13,6 +13,7 @@ function useSession(
onPeerConnected,
onPeerDisconnected,
onPeerData,
onPeerDataProgress,
onPeerTrackAdded,
onPeerTrackRemoved,
onPeerError
@ -76,6 +77,10 @@ function useSession(
onPeerData && onPeerData({ peer, data });
}
function handleDataProgress({ id, count, total }) {
onPeerDataProgress && onPeerDataProgress({ id, count, total });
}
function handleTrack(track, stream) {
onPeerTrackAdded && onPeerTrackAdded({ peer, track, stream });
track.addEventListener("mute", () => {
@ -96,6 +101,7 @@ function useSession(
peer.connection.on("signal", handleSignal);
peer.connection.on("connect", handleConnect);
peer.connection.on("dataComplete", handleDataComplete);
peer.connection.on("dataProgress", handleDataProgress);
peer.connection.on("track", handleTrack);
peer.connection.on("close", handleClose);
peer.connection.on("error", handleError);
@ -105,6 +111,7 @@ function useSession(
handleSignal,
handleConnect,
handleDataComplete,
handleDataProgress,
handleTrack,
handleClose,
handleError,
@ -118,6 +125,7 @@ function useSession(
handleSignal,
handleConnect,
handleDataComplete,
handleDataProgress,
handleTrack,
handleClose,
handleError,
@ -125,6 +133,7 @@ function useSession(
peer.connection.off("signal", handleSignal);
peer.connection.off("connect", handleConnect);
peer.connection.off("dataComplete", handleDataComplete);
peer.connection.off("dataProgress", handleDataProgress);
peer.connection.off("track", handleTrack);
peer.connection.off("close", handleClose);
peer.connection.off("error", handleError);
@ -135,6 +144,7 @@ function useSession(
onPeerConnected,
onPeerDisconnected,
onPeerData,
onPeerDataProgress,
onPeerTrackAdded,
onPeerTrackRemoved,
onPeerError,

View File

@ -33,13 +33,16 @@ function Game() {
const { authenticationStatus, userId, nickname, setNickname } = useContext(
AuthContext
);
const { assetLoadStart, assetLoadFinish } = useContext(MapLoadingContext);
const { assetLoadStart, assetLoadFinish, assetProgressUpdate } = useContext(
MapLoadingContext
);
const { peers, socket, connected } = useSession(
gameId,
handlePeerConnected,
handlePeerDisconnected,
handlePeerData,
handlePeerDataProgress,
handlePeerTrackAdded,
handlePeerTrackRemoved,
handlePeerError
@ -322,7 +325,6 @@ function Game() {
if (cachedMap && cachedMap.lastModified === newMap.lastModified) {
setCurrentMap(cachedMap);
} else {
assetLoadStart();
peer.connection.send({ id: "mapRequest", data: newMap.id });
}
} else {
@ -336,7 +338,6 @@ function Game() {
}
// A new map response with a file attached
if (data.id === "mapResponse") {
assetLoadFinish();
if (data.data && data.data.type === "file") {
const newMap = { ...data.data, file: data.data.file };
putMap(newMap).then(() => {
@ -357,7 +358,6 @@ function Game() {
!cachedToken ||
cachedToken.lastModified !== newToken.lastModified
) {
assetLoadStart();
peer.connection.send({
id: "tokenRequest",
data: newToken.id,
@ -370,7 +370,6 @@ function Game() {
peer.connection.send({ id: "tokenResponse", data: token });
}
if (data.id === "tokenResponse") {
assetLoadFinish();
const newToken = data.data;
if (newToken && newToken.type === "file") {
putToken(newToken);
@ -414,6 +413,16 @@ function Game() {
}
}
function handlePeerDataProgress({ id, total, count }) {
if (count === 1) {
assetLoadStart();
}
if (total === count) {
assetLoadFinish();
}
assetProgressUpdate({ id, total, count });
}
function handlePeerDisconnected(peer) {
setPartyNicknames((prevNicknames) => omit(prevNicknames, [peer.id]));
}