Files
Signlanguage_Datacollector/frontend/src/components/SignDetailPage.tsx

188 lines
6.5 KiB
TypeScript

import React, { useState, useRef, useEffect, ChangeEvent } from 'react';
import { Sign, SignVideo } from '../types/sign';
import { useParams } from 'react-router-dom';
import { 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';
interface Props {
sign?: Sign;
}
type Params = {
id: string;
}
const SignDetailpage: React.FC<Props> = (props) => {
const [sign, setSign] = useState<Sign | null>(props.sign || null);
const [recordedBlob, setRecordedBlob] = useState<Blob | null>(null);
const signVideoRef = useRef<HTMLVideoElement>(null);
const popupVideoRef = useRef<HTMLVideoElement>(null);
const [popUpShown, setPopUpShown] = useState(false);
const [uploadProgress, setUploadProgress] = useState<number | null>(null);
const [videoUrl, setVideoUrl] = useState<string | null>(null);
const [currentVideo, setCurrentVideo] = useState<number | null>(null);
useEffect(() => {
if (recordedBlob) {
setVideoUrl(URL.createObjectURL(recordedBlob));
setPopUpShown(true);
} else {
setVideoUrl(null);
}
}, [recordedBlob]);
const handleUploadProgress = (progess: number) => {
if (progess) {
setUploadProgress(progess);
}
}
const acceptSignVideo = (approved: boolean) => {
// update the sign video in the sign
if (sign != null && currentVideo != null) {
console.log('accepting video');
acceptVideo(sign.id, sign.sign_videos[currentVideo].id, approved).then((response) => {
const newSign = { ...sign };
const newSignVideo = { ...newSign.sign_videos[currentVideo] };
newSignVideo.approved = approved;
newSign.sign_videos[currentVideo] = newSignVideo;
setSign(newSign);
});
}
}
const deleteSignVideo = () => {
deleteVideo(sign!.id, sign!.sign_videos[currentVideo!].id).then((response) => {
const newSign = { ...sign! };
newSign.sign_videos.splice(currentVideo!, 1);
setSign(newSign);
setCurrentVideo(null);
});
}
const handleUpload = async () => {
setUploadProgress(0);
uploadSignVideo(sign!.id, recordedBlob!, handleUploadProgress).then((response) => {
setUploadProgress(100);
// add the new sign video to the sign
console.log(response)
const newSign = { ...sign! };
newSign.sign_videos.push(response);
setSign(newSign);
}).catch((error) => {
setUploadProgress(null);
}
);
}
// get the sign id param
const { id } = useParams<Params>();
useEffect(() => {
if (signVideoRef.current) {
signVideoRef.current.play();
}
}, []);
useEffect(() => {
// if no sign given, get the sign
if (!sign) {
getSign(parseInt(id || '-1')).then((sign) => {
setSign(sign);
});
}
}, [id]);
const dismissPopup = () => {
setPopUpShown(false);
// remove the recorded blob
setRecordedBlob(null);
};
return (
<div>
{
sign ?
<div className="flex">
<div className="w-1/2">
<video loop controls width='100%' height='100%'>
<source src={sign.video_url} type='video/mp4' />
</video>
</div>
<div className="w-1/2">
{currentVideo == null ?
<VideoRecorder
countdownTime={3000}
onRecordingComplete={(blob) => {
setRecordedBlob(blob)
}}
timeLimit={4000}
/> :
<SignVideoPlayer sign_id={sign.id} sign_video={sign.sign_videos[currentVideo]} approveSignVideo={acceptSignVideo} deleteSignVideo={deleteSignVideo} />
}
</div>
</div > : <div>Loading...</div>
}
<div>
<button onClick={() => {
window.location.href = '/';
}} className="bg-white p-2 rounded-full text-red-600 hover:bg-red-600 hover:text-white absolute top-1 left-1">
<svg className="w-6 h-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M10 19l-7-7m0 0l7-7m-7 7h18" />
</svg>
</button>
</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>
}
<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>
<SignVideoGrid currentVideo={currentVideo} sign={sign} setCurrentVideo={setCurrentVideo} />
</div>
);
};
export default SignDetailpage;