refactor: add canPlay check to media message

This commit is contained in:
Tristan Yang
2022-12-29 20:45:14 +08:00
parent 2733600c3b
commit 3e40e2f496
3 changed files with 50 additions and 5 deletions
+19 -1
View File
@@ -8,6 +8,24 @@
<script src="https://cdn.tailwindcss.com"></script>
</head>
<body class="w-sreen h-screen bg-slate-800 text-stone-50"></body>
<body class="w-sreen h-screen flex justify-center items-center bg-slate-800 text-stone-50">
<div class="w-96 flex flex-col gap-2">
<div class="flex flex-col gap-1">
<h2 class="text-gray-100">S3:</h2>
<video class="w-full h-full object-cover" controls>
<source src="https://s.voce.chat/demo/how_to_install_vocechat.mp4" type="video/mp4" />
</video>
</div>
<div class="flex flex-col gap-1">
<h2 class="text-gray-100">VoceChat:</h2>
<video class="w-full h-full object-cover" controls>
<source
src="https://dev.voce.chat/api/resource/file?file_path=2022%2F12%2F29%2F6803d8ad-8857-464b-a0a3-5d0f45bc1682"
type="video/mp4"
/>
</video>
</div>
</div>
</body>
<script src="/widget.js" data-host-id="1" async></script>
</html>
@@ -1,7 +1,8 @@
// import { useState } from 'react';
import { useState } from 'react';
import { formatBytes } from '../../utils';
import IconDownload from "../../../assets/icons/download.svg";
import IconAudio from "../../../assets/icons/file.audio.svg";
import clsx from 'clsx';
type Props = {
url: string,
@@ -11,6 +12,10 @@ type Props = {
}
const AudioMessage = ({ url, name, size, download }: Props) => {
const [canPlay, setCanPlay] = useState(false);
const handleCanPlay = () => {
setCanPlay(true);
};
const _size = formatBytes(size);
return (
<div className='w-96 flex flex-col gap-2 px-3 py-2 rounded-md border border-solid border-gray-300 overflow-hidden bg-[#f1f3f4]'>
@@ -24,7 +29,7 @@ const AudioMessage = ({ url, name, size, download }: Props) => {
</div>
<a href={download} className="mt-2"><IconDownload className="download_icon gray" /></a>
</div>
<audio src={url} controls className="w-full object-cover z-10" />
<audio src={url} onCanPlay={handleCanPlay} controls className={clsx("w-full object-cover z-10", canPlay ? "" : "hidden")} />
</div>
);
};
@@ -1,7 +1,9 @@
import { SyntheticEvent } from 'react';
import { SyntheticEvent, useState } from 'react';
import { Orbit } from "@uiball/loaders";
import { formatBytes } from '../../utils';
import IconDownload from "../../../assets/icons/download.svg";
import IconVideo from "../../../assets/icons/file.video.svg";
// import clsx from 'clsx';
type Props = {
url: string,
@@ -11,6 +13,8 @@ type Props = {
}
const VideoMessage = ({ url, name, size, download }: Props) => {
const [canPlay, setCanPlay] = useState(false);
const [error, setError] = useState(false);
const _size = formatBytes(size);
const handlePlay = (evt: SyntheticEvent<HTMLVideoElement>) => {
const infoEle = evt.currentTarget.previousSibling;
@@ -24,6 +28,14 @@ const VideoMessage = ({ url, name, size, download }: Props) => {
(infoEle as HTMLDivElement).classList.remove("hidden");
}
};
const handleCanPlay = () => {
setCanPlay(true);
};
const handleError = () => {
setCanPlay(false);
setError(true);
};
const tipClass = 'absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2';
return (
<div className='w-96 h-52 relative rounded-md border border-solid border-gray-300 overflow-hidden group'>
<div className="absolute top-0 left-0 w-full h-full bg-black/40 z-20 group-hover:hidden"></div>
@@ -37,7 +49,17 @@ const VideoMessage = ({ url, name, size, download }: Props) => {
</div>
<a href={download} className="mt-2"><IconDownload className="fill-white" /></a>
</div>
<video onPlay={handlePlay} onPause={handlePause} src={url} controls className="absolute left-0 top-0 w-full h-full object-cover z-10" />
{!canPlay ?
<div className={tipClass}>
<Orbit color='#fff' />
</div> :
(error ?
<span className={`${tipClass} text-red-500`}>Error</span> :
null)
}
<video onPlay={handlePlay} onError={handleError} onCanPlay={handleCanPlay} onPause={handlePause} controls={canPlay} className="absolute left-0 top-0 w-full h-full object-cover z-10">
<source src={url} type="video/mp4"></source>
</video>
</div>
);
};