d5f5b5f29b
* function rename * update package.json dependencies to use `^` for semver. I noticed the package-lock.json is not committed in these examples, which seems to be intentional. Is it advisable to use semver for dependencies? This could actually break if someone clones, installs and a newer version of something has a breakage, but in general it might be nice to have folks installing the latest patch releases for deps. * use Upchunk 2.0.0. with 1000x [better progress reporting on uploads](https://github.com/muxinc/upchunk/releases/tag/v2.0.0) **Notice the progress %** Upchunk pre 2.0: ![before-loading](https://user-images.githubusercontent.com/764988/84232581-70fa5080-aaa5-11ea-8db8-2cfe50339b43.gif) Upchunk 2.0: ![after-loading](https://user-images.githubusercontent.com/764988/84232620-85d6e400-aaa5-11ea-82cc-b348ead1f5de.gif)
109 lines
2.7 KiB
JavaScript
109 lines
2.7 KiB
JavaScript
import { useEffect, useRef, useState } from 'react'
|
|
import Router from 'next/router'
|
|
import * as UpChunk from '@mux/upchunk'
|
|
import useSwr from 'swr'
|
|
import Button from './button'
|
|
import Spinner from './spinner'
|
|
import ErrorMessage from './error-message'
|
|
|
|
const fetcher = (url) => {
|
|
return fetch(url).then((res) => res.json())
|
|
}
|
|
|
|
const UploadForm = () => {
|
|
const [isUploading, setIsUploading] = useState(false)
|
|
const [isPreparing, setIsPreparing] = useState(false)
|
|
const [uploadId, setUploadId] = useState(null)
|
|
const [progress, setProgress] = useState(null)
|
|
const [errorMessage, setErrorMessage] = useState('')
|
|
const inputRef = useRef(null)
|
|
|
|
const { data, error } = useSwr(
|
|
() => (isPreparing ? `/api/upload/${uploadId}` : null),
|
|
fetcher,
|
|
{ refreshInterval: 5000 }
|
|
)
|
|
|
|
const upload = data && data.upload
|
|
|
|
useEffect(() => {
|
|
if (upload && upload.asset_id) {
|
|
Router.push({
|
|
pathname: `/asset/${upload.asset_id}`,
|
|
scroll: false,
|
|
})
|
|
}
|
|
}, [upload])
|
|
|
|
if (error) return <ErrorMessage message="Error fetching api" />
|
|
if (data && data.error) return <ErrorMessage message={data.error} />
|
|
|
|
const createUpload = async () => {
|
|
try {
|
|
return fetch('/api/upload', {
|
|
method: 'POST',
|
|
})
|
|
.then((res) => res.json())
|
|
.then(({ id, url }) => {
|
|
setUploadId(id)
|
|
return url
|
|
})
|
|
} catch (e) {
|
|
console.error('Error in createUpload', e)
|
|
setErrorMessage('Error creating upload')
|
|
}
|
|
}
|
|
|
|
const startUpload = (evt) => {
|
|
setIsUploading(true)
|
|
const upload = UpChunk.createUpload({
|
|
endpoint: createUpload,
|
|
file: inputRef.current.files[0],
|
|
})
|
|
|
|
upload.on('error', (err) => {
|
|
setErrorMessage(err.detail)
|
|
})
|
|
|
|
upload.on('progress', (progress) => {
|
|
setProgress(Math.floor(progress.detail))
|
|
})
|
|
|
|
upload.on('success', () => {
|
|
setIsPreparing(true)
|
|
})
|
|
}
|
|
|
|
if (errorMessage) return <ErrorMessage message={errorMessage} />
|
|
|
|
return (
|
|
<>
|
|
<div className="container">
|
|
{isUploading ? (
|
|
<>
|
|
{isPreparing ? (
|
|
<div>Preparing..</div>
|
|
) : (
|
|
<div>Uploading...{progress ? `${progress}%` : ''}</div>
|
|
)}
|
|
<Spinner />
|
|
</>
|
|
) : (
|
|
<label>
|
|
<Button type="button" onClick={() => inputRef.current.click()}>
|
|
Select a video file
|
|
</Button>
|
|
<input type="file" onChange={startUpload} ref={inputRef} />
|
|
</label>
|
|
)}
|
|
</div>
|
|
<style jsx>{`
|
|
input {
|
|
display: none;
|
|
}
|
|
`}</style>
|
|
</>
|
|
)
|
|
}
|
|
|
|
export default UploadForm
|