feat(video): add video loading error handling and status display

- Add new error message for video loading failure in i18n
- Implement video loading state and error handling in VideoViewer
- Display appropriate UI for loading errors when video fails to load
This commit is contained in:
icarus 2025-10-12 03:34:22 +08:00
parent d982c659d3
commit 46221985bd
2 changed files with 20 additions and 5 deletions

View File

@ -4647,7 +4647,8 @@
}, },
"video": { "video": {
"error": { "error": {
"invalid": "Invalid video" "invalid": "Invalid video",
"load": "Failed to load the video"
}, },
"prompt": { "prompt": {
"placeholder": "describes the video to generate" "placeholder": "describes the video to generate"

View File

@ -11,6 +11,7 @@ export interface VideoProps {
export const VideoViewer = ({ video: _video }: VideoProps) => { export const VideoViewer = ({ video: _video }: VideoProps) => {
const { t } = useTranslation() const { t } = useTranslation()
const [video, setVideo] = useState<Video | undefined>(_video) const [video, setVideo] = useState<Video | undefined>(_video)
const [loadSuccess, setLoadSuccess] = useState<boolean | undefined>(undefined)
return ( return (
<> <>
{/* For test */} {/* For test */}
@ -18,11 +19,11 @@ export const VideoViewer = ({ video: _video }: VideoProps) => {
label="Status" label="Status"
value={video?.status} value={video?.status}
onValueChange={(v) => { onValueChange={(v) => {
if (v) setVideo({ ...video, status: v as VideoStatus } as Video) if (v !== 'undefined') setVideo({ ..._video, status: v as VideoStatus, progress: 60 } as Video)
else setVideo(undefined) else setVideo(undefined)
}} }}
orientation="horizontal" orientation="horizontal"
className="absolute rounded-2xl bg-foreground-100 p-4"> className="absolute z-100 rounded-2xl bg-foreground-100 p-4">
<Radio value="undefined">undefined</Radio> <Radio value="undefined">undefined</Radio>
<Radio value="queued">queued</Radio> <Radio value="queued">queued</Radio>
<Radio value="in_progress">in_progress</Radio> <Radio value="in_progress">in_progress</Radio>
@ -71,14 +72,27 @@ export const VideoViewer = ({ video: _video }: VideoProps) => {
/> />
</div> </div>
)} )}
{/* TODO: complete video widget */} {video && video.status === 'downloaded' && loadSuccess !== false && (
{video && video.status === 'downloaded' && <video></video>} <video
controls
className="h-full w-full"
onLoadedData={() => setLoadSuccess(true)}
onError={() => setLoadSuccess(false)}>
<source src="video.mp4" type="video/mp4" />
</video>
)}
{video && video.status === 'failed' && ( {video && video.status === 'failed' && (
<div className="flex h-full w-full flex-col items-center justify-center rounded-2xl bg-danger-200"> <div className="flex h-full w-full flex-col items-center justify-center rounded-2xl bg-danger-200">
<CircleXIcon size={64} className="fill-danger text-danger-200" /> <CircleXIcon size={64} className="fill-danger text-danger-200" />
<span className="font-bold text-2xl">{t('video.status.failed')}</span> <span className="font-bold text-2xl">{t('video.status.failed')}</span>
</div> </div>
)} )}
{video && video.status === 'downloaded' && loadSuccess === false && (
<div className="flex h-full w-full flex-col items-center justify-center rounded-2xl bg-danger-200">
<CircleXIcon size={64} className="fill-danger text-danger-200" />
<span className="font-bold text-2xl">{t('video.error.load')}</span>
</div>
)}
</div> </div>
</> </>
) )