silphius/app/routes/_main-menu.play.$/route.jsx
2024-09-21 06:24:26 -05:00

85 lines
2.2 KiB
JavaScript

import {settings} from '@pixi/core';
import {json, useLoaderData} from "@remix-run/react";
import {useEffect, useState} from 'react';
import {Outlet, useParams} from 'react-router-dom';
import {
computeMissing,
fetchResources,
get,
readAsset,
set,
} from '@/util/resources.js';
import styles from './play.module.css';
settings.ADAPTER.fetch = async (path) => {
const resource = await readAsset(path);
return resource ? new Response(resource) : new Response(undefined, {status: 404});
};
export async function loader({request}) {
const {juggleSession} = await import('@/server/session.server.js');
const {loadManifest} = await import('@/util/resources.server.js');
await juggleSession(request);
return json({
manifest: await loadManifest(),
});
}
export default function Play() {
const {manifest} = useLoaderData();
const [Client, setClient] = useState();
const params = useParams();
const [type] = params['*'].split('/');
useEffect(() => {
const controller = new AbortController();
const {signal} = controller;
async function receiveResources() {
const current = await get();
const paths = await computeMissing(current, manifest);
if (paths.length > 0 && !signal.aborted) {
try {
const resources = await fetchResources(paths, {signal});
if (resources) {
for (const key in resources) {
current[key] = resources[key];
}
await set(current);
}
}
catch (e) {
if ((e instanceof DOMException) && 'AbortError' === e.name) {
return;
}
throw e;
}
}
}
receiveResources();
return () => {
controller.abort();
};
}, [manifest]);
useEffect(() => {
async function loadClient() {
let Client;
switch (type) {
case 'local':
({default: Client} = await import('@/client/local.js'));
break;
case 'remote':
({default: Client} = await import('@/client/remote.js'));
break;
}
setClient(() => Client);
}
loadClient();
}, [type]);
return (
<div className={styles.play}>
<Outlet context={Client} />
</div>
);
}