import {json} from "@remix-run/node"; import {useEffect, useState} from 'react'; import {useOutletContext, useParams} from 'react-router-dom'; import ClientContext from '@/context/client.js'; import MainEntityContext from '@/context/main-entity.js'; import Ui from '@/react-components/ui.jsx'; import {juggleSession} from '@/session.server'; export async function loader({request}) { await juggleSession(request); return json({}); } export default function PlaySpecific() { const Client = useOutletContext(); const [client, setClient] = useState(); const mainEntityTuple = useState(); const [disconnected, setDisconnected] = useState(false); const params = useParams(); const [type, url] = params['*'].split('/'); useEffect(() => { if (!Client) { return; } const client = new Client(); async function connect() { await client.connect(url); setClient(client); } connect(); return () => { client.disconnect(); }; }, [Client, url]); // Sneakily use beforeunload to snag some time to save. useEffect(() => { if ('local' !== type) { return; } async function onBeforeUnload(event) { client.disconnect(); function waitForSave() { return new Promise((resolve) => setTimeout(resolve, 0)); } while (client.worker) { await waitForSave(); } } addEventListener('beforeunload', onBeforeUnload); return () => { removeEventListener('beforeunload', onBeforeUnload); }; }); useEffect(() => { if (!client) { return; } function onConnectionStatus(status) { switch (status) { case 'aborted': { setDisconnected(true); break; } case 'connected': { setDisconnected(false); break; } } } client.addPacketListener('ConnectionStatus', onConnectionStatus); return () => { client.removePacketListener('ConnectionStatus', onConnectionStatus); }; }, [client]); useEffect(() => { if (!disconnected) { return; } async function reconnect() { await client.connect(url); } reconnect(); const handle = setInterval(reconnect, 1000); return () => { clearInterval(handle); }; }, [client, disconnected, url]); return ( ); }