import { h } from 'preact'
import { useState, useEffect } from 'preact/hooks'
import { engineByFilename } from './common/engines'
import Player from './Player'
import Status from './Status/Status'
const INITIAL_STATUS = {
stage: 'loading',
details: ['Loading'],
}
const prepareVM = ({ url, setStatus, setParts }) => {
const st = (stage, details) => (args) => {
setStatus({ stage, details: [details] })
return args
}
const cleanUrl = (url) =>
url.startsWith('blob:')
? url.replace(/#(.*)$/g, '')
: url
const fetchWasm = (wasmBinaryName) =>
fetch(wasmBinaryName)
.then((response) => response.arrayBuffer())
const checkResponse = (response) => {
if (response.ok) return response
throw new Error(response.statusText)
}
return Promise.resolve(url)
.then(st('loading', 'Downloading file'))
.then(cleanUrl)
.then(fetch)
.then(checkResponse)
.then(st('loading', 'Processing file'))
.then((response) => response.arrayBuffer())
.then((arrayBuffer) => new Uint8Array(arrayBuffer))
.then(st('loading', 'Downloading engine'))
.then((storyfile) => {
let parts = engineByFilename(url)
return [storyfile, parts.engine, parts.wasmBinaryName]
})
.then(([storyfile, engine, wasmBinaryName]) => Promise.all([
storyfile, engine, fetchWasm(wasmBinaryName),
]))
.then(([storyfile, engine, wasmBinary]) => setParts({
storyfile, engine, wasmBinary,
}))
.then(st('loading', 'Running'))
.catch((e) => {
console.error(e)
setStatus({ stage: 'fail', details: [e.message, url] })
})
}
export default function UrlPlayer ({
url, singleWindow, onFullscreenRequest, setMenuOpen,
}) {
const [status, setStatus] = useState(INITIAL_STATUS)
const [vmParts, setParts] = useState(null)
useEffect(() => {
setStatus(INITIAL_STATUS)
setParts(null)
prepareVM({ url, setStatus, setParts })
return () => setParts(null)
}, [url])
return vmParts
? ()
: ()
}