Skip to content

Commit

Permalink
Add a fallback for browsers that do not support DecompressionStream
Browse files Browse the repository at this point in the history
  • Loading branch information
shartte committed Jul 4, 2023
1 parent 1e7b6ca commit 8555930
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 10 deletions.
13 changes: 13 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"dependencies": {
"@tippyjs/react": "^4.2.6",
"flatbuffers": "^23.5.26",
"pako": "^2.1.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.13.0",
Expand All @@ -24,6 +25,7 @@
"devDependencies": {
"@types/mdast": "^3.0.11",
"@types/node": "^20.3.3",
"@types/pako": "^2.0.0",
"@types/react": "^18.0.37",
"@types/react-dom": "^18.0.11",
"@types/three": "^0.152.1",
Expand Down
13 changes: 6 additions & 7 deletions src/GuideLoader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { PropsWithChildren, useMemo } from "react";
import useLoadEffect from "./data/useLoadEffect.ts";
import { Guide, GuideProvider } from "./data/Guide.ts";
import LoadState from "./components/LoadState.tsx";
import decompress from "./decompress.ts";

export type GuideLoaderProps = PropsWithChildren<{
version: GuideVersion;
Expand All @@ -26,18 +27,16 @@ async function loadGuideFromResponseV1(
): Promise<Guide> {
const guideDataUrl = new URL(metadata.guideDataPath, metadataUrl);

const response = await fetch(guideDataUrl, {
let response = await fetch(guideDataUrl, {
cache: "force-cache",
});

// Decompress
const blob = await response.blob();
const ds = new DecompressionStream("gzip");
const decompressedStream = blob.stream().pipeThrough(ds);
const jsonBody = await new Response(decompressedStream).json();
response = await decompress(response);
const jsonBody = await response.json();

// Use the directory we loaded the guide from to load further assets
const baseUrl = new URL("./", response.url).toString();
const baseUrl = new URL("./", guideDataUrl).toString();
console.info("Deducing base URL %s for guide data %s", baseUrl, response.url);
return new Guide(
baseUrl,
Expand Down Expand Up @@ -78,7 +77,7 @@ function GuideLoader({ version, children }: GuideLoaderProps) {
} else {
return (
<LoadState
operation={`Loading Guide for ${version.gameVersion}`}
operation={`Guide for ${version.gameVersion}`}
result={loadResult}
/>
);
Expand Down
7 changes: 4 additions & 3 deletions src/components/model-viewer/loadScene.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Group, Mesh } from "three";
import TextureManager from "./TextureManager.ts";
import loadGeometry from "./loadGeometry.ts";
import loadMaterial from "./loadMaterial.ts";
import decompress from "../../decompress.ts";

type LoadedScene = {
group: Group;
Expand All @@ -19,9 +20,8 @@ export type CameraProps = {

async function decompressResponse(response: Response) {
const blob = await response.blob();
const ds = new DecompressionStream("gzip");
const decompressedStream = blob.stream().pipeThrough(ds);
const sceneContent = await new Response(decompressedStream).arrayBuffer();
response = await decompress(blob);
const sceneContent = await response.arrayBuffer();

console.debug(
"Loaded %s, %d byte compressed, %d byte uncompressed",
Expand Down Expand Up @@ -79,5 +79,6 @@ export default async function loadScene(
roll: expCamera.roll(),
zoom: expCamera.zoom(),
};

return { cameraProps, group };
}
23 changes: 23 additions & 0 deletions src/decompress.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
export default async function decompress(response: Response): Promise<Response>;
export default async function decompress(blob: Blob): Promise<Response>;
export default async function decompress(
response: Response | Blob
): Promise<Response> {
let blob: Blob;
if (response instanceof Blob) {
blob = response;
} else {
blob = await response.blob();
}

// Fallback for browsers without support for DecompressionStream
if (typeof DecompressionStream === "undefined") {
const fallbackDecompress = await import("./decompressFallback.ts");
const data = await fallbackDecompress.default(blob);
return new Response(data);
}

const ds = new DecompressionStream("gzip");
const decompressedStream = blob.stream().pipeThrough(ds);
return new Response(decompressedStream);
}
8 changes: 8 additions & 0 deletions src/decompressFallback.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { ungzip } from "pako";

export default async function decompressFallback(
blob: Blob
): Promise<Uint8Array> {
const data = await blob.arrayBuffer();
return ungzip(data);
}

0 comments on commit 8555930

Please sign in to comment.