feat(video): add status handling and error messages to video player

- Add new i18n strings for video status and error messages
- Implement status-based UI rendering with progress indicators
- Include test radio group for status simulation
This commit is contained in:
icarus 2025-10-12 03:13:23 +08:00
parent 85c8d5fca2
commit dc19c17526
2 changed files with 71 additions and 8 deletions

View File

@ -4652,6 +4652,13 @@
"prompt": {
"placeholder": "describes the video to generate"
},
"status": {
"completed": "Generation Completed",
"downloading": "Downloading",
"failed": "Failed to generate video",
"in_progress": "Generating",
"queued": "Queued"
},
"title": "Video",
"undefined": "No available video"
},

View File

@ -1,22 +1,78 @@
import { Video } from '@renderer/types/video'
import { CircleXIcon } from 'lucide-react'
import { Progress, Radio, RadioGroup, Spinner } from '@heroui/react'
import { Video, VideoStatus } from '@renderer/types/video'
import { CheckCircleIcon, CircleXIcon } from 'lucide-react'
import { useState } from 'react'
import { useTranslation } from 'react-i18next'
export interface VideoProps {
video?: Video | null
video?: Video
}
export const VideoPlayer = ({ video }: VideoProps) => {
export const VideoPlayer = ({ video: _video }: VideoProps) => {
const { t } = useTranslation()
const [video, setVideo] = useState<Video | undefined>(_video)
return (
<div className="flex h-full w-full items-center justify-center rounded-2xl bg-foreground-200">
{/* TODO: complete video widget */}
{video && <video></video>}
{/* For test */}
<RadioGroup
label="Status"
onValueChange={(v) => {
if (v) setVideo({ ...video, status: v as VideoStatus } as Video)
else setVideo(undefined)
}}>
<Radio value="undefined">undefined</Radio>
<Radio value="queued">queued</Radio>
<Radio value="in_progress">in_progress</Radio>
<Radio value="completed">completed</Radio>
<Radio value="downloading">downloading</Radio>
<Radio value="downloaded">downloaded</Radio>
<Radio value="failed">failed</Radio>
</RadioGroup>
{video === undefined && t('video.undefined')}
{video === null && (
{video && video.status === 'queued' && (
<div className="flex h-full w-full flex-col items-center justify-center rounded-2xl">
<Spinner variant="dots" />
<span>{t('video.status.queued')}</span>
</div>
)}
{video && video.status === 'in_progress' && (
<div className="flex h-full w-full flex-col items-center justify-center rounded-2xl">
<Progress
label={t('video.status.in_progress')}
aria-label={t('video.status.in_progress')}
className="max-w-md"
color="primary"
showValueLabel={true}
size="md"
value={video.progress}
/>
</div>
)}
{video && video.status === 'completed' && (
<div className="flex h-full w-full flex-col items-center justify-center rounded-2xl bg-success-100">
<CheckCircleIcon size={64} className="fill-success text-success-100" />
<span className="font-bold text-2xl">{t('video.status.completed')}</span>
</div>
)}
{video && video.status === 'downloading' && (
<div className="flex h-full w-full flex-col items-center justify-center rounded-2xl">
<Progress
label={t('video.status.downloading')}
aria-label={t('video.status.downloading')}
className="max-w-md"
color="primary"
showValueLabel={true}
size="md"
value={video.progress}
/>
</div>
)}
{/* TODO: complete video widget */}
{video && video.status === 'downloaded' && <video></video>}
{video && video.status === 'failed' && (
<div className="flex h-full w-full flex-col items-center justify-center rounded-2xl bg-danger-100">
<CircleXIcon size={64} className="fill-danger text-danger-100" />
<span className="font-bold text-2xl">{t('video.error.invalid')}</span>
<span className="font-bold text-2xl">{t('video.status.failed')}</span>
</div>
)}
</div>