54 lines
1.6 KiB
TypeScript
54 lines
1.6 KiB
TypeScript
import { useEffect, useRef, useState } from "react";
|
|
import { useNavigate, useParams } from "react-router-dom";
|
|
import type { PlayerHandle } from "../player";
|
|
import { Icon } from "../ui/Icon";
|
|
|
|
export function Play() {
|
|
const { versionId } = useParams();
|
|
const navigate = useNavigate();
|
|
const host = useRef<HTMLDivElement>(null);
|
|
const [status, setStatus] = useState("Загрузка…");
|
|
const [error, setError] = useState("");
|
|
|
|
useEffect(() => {
|
|
let engine: PlayerHandle | null = null;
|
|
let cancelled = false;
|
|
// the player is a separate chunk: the library UI does not pay for it
|
|
import("../player").then(({ launch }) =>
|
|
launch(host.current!, Number(versionId), () => navigate(-1), setStatus),
|
|
).then((e) => {
|
|
if (cancelled) e.destroy();
|
|
else {
|
|
engine = e;
|
|
setStatus("");
|
|
}
|
|
}).catch((e) => setError((e as Error).message));
|
|
return () => {
|
|
cancelled = true;
|
|
engine?.destroy();
|
|
};
|
|
}, [versionId, navigate]);
|
|
|
|
return (
|
|
<div className="play">
|
|
<div ref={host} className="play-host" />
|
|
{(status || error) && (
|
|
<div className="play-status">
|
|
{error ? (
|
|
<>
|
|
<Icon name="alert" size={36} />
|
|
<span className="error-text">{error}</span>
|
|
<button className="btn" onClick={() => navigate(-1)}><Icon name="back" size={18} />Назад</button>
|
|
</>
|
|
) : (
|
|
<>
|
|
<span className="spinner" />
|
|
{status}
|
|
</>
|
|
)}
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|