Skip to content

Commit

Permalink
fix: prevent map not showing up at all on the player section if it is…
Browse files Browse the repository at this point in the history
… published while being loaded.
  • Loading branch information
n1ru4l committed Mar 26, 2021
1 parent 29d2fa5 commit 3eeedbf
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 38 deletions.
87 changes: 49 additions & 38 deletions src/player-area.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import useAsyncEffect from "@n1ru4l/use-async-effect";
import debounce from "lodash/debounce";
import { ReactRelayContext } from "relay-hooks";
import styled from "@emotion/styled/macro";
import { loadImage } from "./util";
import { loadImage, LoadImageTask } from "./util";
import { Toolbar } from "./toolbar";
import * as Icons from "./feather-icons";
import { SplashScreen } from "./splash-screen";
Expand Down Expand Up @@ -79,7 +79,8 @@ const PlayerMap: React.FC<{
* used for canceling pending requests in case there is a new update incoming.
* should be either null or an array of tasks returned by loadImage
*/
const pendingFogImageLoad = React.useRef<(() => void) | null>(null);
const pendingMapImageLoad = React.useRef<LoadImageTask | null>(null);
const pendingFogImageLoad = React.useRef<LoadImageTask | null>(null);
const [markedAreas, setMarkedAreas] = React.useState<MarkedArea[]>(() => []);

const [refetchTrigger, setRefetchTrigger] = React.useState(0);
Expand All @@ -88,81 +89,91 @@ const PlayerMap: React.FC<{
if (!data) {
return;
}

if (window.document.visibilityState === "hidden") {
return;
}

if (pendingFogImageLoad.current) {
pendingFogImageLoad.current?.();
pendingFogImageLoad.current?.cancel();
pendingFogImageLoad.current = null;
}

/**
* Hide map (show splashscreen)
*/
if (!data.map) {
pendingMapImageLoad.current?.cancel();
currentMapRef.current = null;
setCurrentMap(null);
setFogImage(null);
setMapImage(null);
return;
}

/**
* Fog has updated
*/
if (currentMapRef.current && currentMapRef.current.id === data.map.id) {
const imageUrl = buildApiUrl(
if (
currentMapRef.current &&
currentMapRef.current.id === data.map.id &&
pendingMapImageLoad.current
) {
const fogImageUrl = buildApiUrl(
// prettier-ignore
`/map/${data.map.id}/fog-live?cache_buster=${createCacheBusterString()}&authorization=${encodeURIComponent(pcPassword)}`
);

const task = loadImage(imageUrl);
pendingFogImageLoad.current = () => task.cancel();

task.promise
.then((fogImage) => {
setFogImage(fogImage);
})
.catch(() => {
console.log("Cancel loading image.");
});
return;
}
const task = loadImage(fogImageUrl);
pendingFogImageLoad.current = task;
} else {
// Load new map
pendingMapImageLoad.current?.cancel();
currentMapRef.current = data.map;

/**
* Load new map
*/
currentMapRef.current = data.map;
const mapImageUrl = buildApiUrl(
// prettier-ignore
`/map/${data.map.id}/map?authorization=${encodeURIComponent(pcPassword)}`
);

const mapImageUrl = buildApiUrl(
// prettier-ignore
`/map/${data.map.id}/map?authorization=${encodeURIComponent(pcPassword)}`
);
const fogImageUrl = buildApiUrl(
// prettier-ignore
`/map/${data.map.id}/fog-live?cache_buster=${createCacheBusterString()}&authorization=${encodeURIComponent(pcPassword)}`
);

const fogImageUrl = buildApiUrl(
// prettier-ignore
`/map/${data.map.id}/fog-live?cache_buster=${createCacheBusterString()}&authorization=${encodeURIComponent(pcPassword)}`
);
const loadMapImageTask = loadImage(mapImageUrl);
const loadFogImageTask = loadImage(fogImageUrl);

const loadMapImageTask = loadImage(mapImageUrl);
const loadFogImageTask = loadImage(fogImageUrl);
pendingMapImageLoad.current = loadMapImageTask;
pendingFogImageLoad.current = loadFogImageTask;

pendingFogImageLoad.current = () => {
loadMapImageTask.cancel();
loadFogImageTask.cancel();
};
setCurrentMap(data.map);
setMapImage(null);
setFogImage(null);
}

Promise.all([loadMapImageTask.promise, loadFogImageTask.promise])
Promise.all([
pendingMapImageLoad.current.promise,
pendingFogImageLoad.current.promise,
])
.then(([mapImage, fogImage]) => {
setMapImage(mapImage);
setFogImage(fogImage);
setCurrentMap(data.map);
})
.catch(() => {
console.log("Cancel loading image.");
});
}, []);

React.useEffect(
() => () => {
// cleanup in case the component unmounts
pendingMapImageLoad.current?.cancel();
pendingFogImageLoad.current?.cancel();
},
[]
);

useAsyncEffect(
function* (_, cast) {
const result = yield* cast(
Expand All @@ -176,7 +187,7 @@ const PlayerMap: React.FC<{

return () => {
if (pendingFogImageLoad.current) {
pendingFogImageLoad.current?.();
pendingFogImageLoad.current.cancel();
pendingFogImageLoad.current = null;
}
};
Expand Down
4 changes: 4 additions & 0 deletions src/util.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import * as React from "react";

export type LoadImageTask = {
promise: Promise<HTMLImageElement>;
cancel: () => void;
};
/**
* Utility for preloading an image as a promise
*/
Expand Down

1 comment on commit 3eeedbf

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This image has been published to DockerHub. 🐋

You can easily try this build out locally with Docker.

docker run -p 3000:3000 dungeonrevealer/dungeon-revealer:3eeedbfad42e85fd309f9b8094dbab12545b136f

Please sign in to comment.