202 lines
7.8 KiB
TypeScript
Executable File
202 lines
7.8 KiB
TypeScript
Executable File
import React, { useState, useRef, useEffect, ChangeEvent } from 'react';
|
|
import { Sign, SignVideo, SimpleSign } from '../types/sign';
|
|
import { useParams } from 'react-router-dom';
|
|
import { getRandomSign, getSign } from '../services/signs';
|
|
import ReactModal from 'react-modal';
|
|
import { acceptVideo, deleteVideo, uploadSignVideo } from '../services/signvideos';
|
|
import { LoadingButton } from './loading-button/loading-button';
|
|
import VideoRecorder from 'react-video-recorder';
|
|
import SignVideoGrid from './SignVideoGrid';
|
|
import SignVideoPlayer from './SignVideoPlayer';
|
|
|
|
|
|
const RandomSignUpload: React.FC = () => {
|
|
|
|
const [sign, setSign] = useState<SimpleSign | null>(null);
|
|
const [signVideo, setSignVideo] = useState<string | null>(null);
|
|
|
|
const [recordedBlob, setRecordedBlob] = useState<Blob | null>(null);
|
|
const signVideoRef = useRef<HTMLVideoElement>(null);
|
|
|
|
const popupVideoRef = useRef<HTMLVideoElement>(null);
|
|
const [popUpShown, setPopUpShown] = useState(false);
|
|
const [recorderKey, setRecorderKey] = useState(1);
|
|
const [uploadProgress, setUploadProgress] = useState<number | null>(null);
|
|
const [videoUrl, setVideoUrl] = useState<string | null>(null);
|
|
|
|
useEffect(() => {
|
|
if (recordedBlob) {
|
|
setVideoUrl(URL.createObjectURL(recordedBlob));
|
|
setPopUpShown(true);
|
|
} else {
|
|
setVideoUrl(null);
|
|
}
|
|
}, [recordedBlob]);
|
|
|
|
const handleUploadProgress = (progess: number) => {
|
|
if (progess) {
|
|
setUploadProgress(progess);
|
|
}
|
|
}
|
|
|
|
|
|
const handleUpload = async () => {
|
|
setUploadProgress(0);
|
|
uploadSignVideo(sign!.id, recordedBlob!, handleUploadProgress).then((response) => {
|
|
|
|
console.log("upload complete");
|
|
setPopUpShown(false);
|
|
// get new random sign
|
|
get_random_sign();
|
|
|
|
// add the new sign video to the sign
|
|
const newSign = { ...sign! };
|
|
|
|
setSign(newSign);
|
|
setUploadProgress(100);
|
|
}).catch((error) => {
|
|
setUploadProgress(null);
|
|
}
|
|
);
|
|
}
|
|
|
|
useEffect(() => {
|
|
if (signVideoRef.current) {
|
|
signVideoRef.current.play();
|
|
}
|
|
}, []);
|
|
|
|
const get_random_sign = () => {
|
|
getRandomSign().then((response) => {
|
|
// check if the sign is different from the current one
|
|
if (sign === null || sign.id !== response.id) {
|
|
setSign(response);
|
|
setUploadProgress(null);
|
|
// set the video url
|
|
setSignVideo(response.video_url);
|
|
} else {
|
|
// get a new sign
|
|
get_random_sign();
|
|
}
|
|
}
|
|
);
|
|
}
|
|
|
|
|
|
useEffect(() => {
|
|
// get random sign
|
|
get_random_sign();
|
|
}, []);
|
|
|
|
const dismissPopup = () => {
|
|
setPopUpShown(false);
|
|
// remove the recorded blob
|
|
setRecordedBlob(null);
|
|
};
|
|
|
|
return (
|
|
<div>
|
|
|
|
{
|
|
sign ? <div>
|
|
<div className="flex items-center justify-between">
|
|
<h1 className="text-8xl font-bold mx-auto text-center">{sign.name}</h1>
|
|
</div>
|
|
<div className="flex">
|
|
<button className="ml-auto p-2 rounded-full text-red-600 hover:bg-red-600 hover:text-white" onClick={get_random_sign}>
|
|
Skip
|
|
</button>
|
|
</div>
|
|
|
|
<div className="flex">
|
|
|
|
{
|
|
signVideo &&
|
|
<div className="w-1/2">
|
|
<video key={signVideo} loop controls width='100%' height='100%'>
|
|
<source src={signVideo} type='video/mp4' />
|
|
</video>
|
|
</div>
|
|
}
|
|
|
|
|
|
<div id="recorder-wrapper" className="w-1/2">
|
|
<VideoRecorder
|
|
key={recorderKey}
|
|
countdownTime={3000}
|
|
onRecordingComplete={(blob) => {
|
|
setRecordedBlob(blob)
|
|
// reset the VideoRecorder
|
|
setRecorderKey(prevKey => prevKey + 1);
|
|
}}
|
|
showReplayControls={false}
|
|
replayVideoAutoplayAndLoopOff={true}
|
|
isOnInitially
|
|
timeLimit={4000}
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div > : <div>Loading...</div>
|
|
}
|
|
<ReactModal
|
|
isOpen={popUpShown}
|
|
shouldCloseOnOverlayClick={false}
|
|
className="modal bg-white rounded-3xl bg-gray-300 p-7"
|
|
ariaHideApp={false}
|
|
style={{
|
|
content: {
|
|
|
|
position: "absolute",
|
|
top: '50%',
|
|
left: '50%',
|
|
transform: 'translate(-50%, -50%)',
|
|
},
|
|
}}
|
|
>
|
|
{videoUrl &&
|
|
<div>
|
|
<video key="vid" ref={popupVideoRef} src={videoUrl!} controls loop className="pb-4" />
|
|
<LoadingButton title="Upload" onClick={handleUpload} progress={uploadProgress} />
|
|
</div>
|
|
}
|
|
{(uploadProgress === null || uploadProgress === 0) &&
|
|
<button onClick={dismissPopup} className="bg-white p-2 rounded-full text-red-600 hover:bg-red-600 hover:text-white absolute top-1 right-1">
|
|
<svg className="w-6 h-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M6 18L18 6M6 6l12 12" />
|
|
</svg>
|
|
</button>
|
|
}
|
|
</ReactModal>
|
|
<div>
|
|
<p className="ml-4 text-lg font-bold my-4">Hoe werkt het?</p>
|
|
<div className="ml-4 flex flex-col my-4">
|
|
<div className="flex items-center">
|
|
<span className="text-xl font-bold mr-2">Stap 1:</span>
|
|
<span className="text-lg">Bekijk de video aan de linkerkant en doe het teken zelf na (bovenlichaam moet zichtbaar zijn).</span>
|
|
</div>
|
|
<div className="flex items-center mt-2">
|
|
<span className="text-xl font-bold mr-2">Stap 2:</span>
|
|
<span className="text-lg">Klik op de rode opnameknop om uw eigen video op te nemen.</span>
|
|
</div>
|
|
<div className="flex items-center mt-2">
|
|
<span className="text-xl font-bold mr-2">Stap 3:</span>
|
|
<span className="text-lg">Voer het teken uit en spreek het woord uit.</span>
|
|
</div>
|
|
<div className="flex items-center mt-2">
|
|
<span className="text-xl font-bold mr-2">Stap 4:</span>
|
|
<span className="text-lg">Zodra u uw video hebt opgenomen, kunt u ervoor kiezen om deze te uploaden door op de knop 'Uploaden' te klikken of het pop-upvenster te sluiten.</span>
|
|
</div>
|
|
<div className="flex items-center mt-2">
|
|
<span className="text-xl font-bold mr-2">Stap 5:</span>
|
|
<span className="text-lg">Uw video wordt beoordeeld door ons team.</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
);
|
|
};
|
|
|
|
|
|
export default RandomSignUpload;
|