diff --git a/src/components/LoadingOverlay.js b/src/components/LoadingOverlay.js
index eca0d0b..f6a30be 100644
--- a/src/components/LoadingOverlay.js
+++ b/src/components/LoadingOverlay.js
@@ -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 (
+ {progress && (
+
+ )}
);
}
diff --git a/src/components/map/Map.js b/src/components/map/Map.js
index b7a1119..198f826 100644
--- a/src/components/map/Map.js
+++ b/src/components/map/Map.js
@@ -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}
- {isLoading && }
+ {isLoading && }
>
}
selectedToolId={selectedToolId}
diff --git a/src/contexts/MapLoadingContext.js b/src/contexts/MapLoadingContext.js
index 13ec1d7..12f0f4a 100644
--- a/src/contexts/MapLoadingContext.js
+++ b/src/contexts/MapLoadingContext.js
@@ -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 (
diff --git a/src/helpers/Peer.js b/src/helpers/Peer.js
index 5a5a385..32984eb 100644
--- a/src/helpers/Peer.js
+++ b/src/helpers/Peer.js
@@ -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
diff --git a/src/helpers/useSession.js b/src/helpers/useSession.js
index 22076f6..282ceba 100644
--- a/src/helpers/useSession.js
+++ b/src/helpers/useSession.js
@@ -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,
diff --git a/src/routes/Game.js b/src/routes/Game.js
index f479a7a..9acfdd0 100644
--- a/src/routes/Game.js
+++ b/src/routes/Game.js
@@ -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]));
}