mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2025-12-28 13:31:32 +08:00
feat(video): add VideoPlayer component with file loading
Implement VideoPlayer component that fetches video file path using FileManager and displays it with loading skeleton. This improves video loading reliability by handling file existence checks and error states.
This commit is contained in:
parent
8518734e48
commit
c20394f460
@ -6,14 +6,17 @@ import {
|
||||
ModalContent,
|
||||
ModalFooter,
|
||||
Progress,
|
||||
Skeleton,
|
||||
Spinner,
|
||||
useDisclosure
|
||||
} from '@heroui/react'
|
||||
import { Video, VideoFailed } from '@renderer/types/video'
|
||||
import FileManager from '@renderer/services/FileManager'
|
||||
import { Video, VideoDownloaded, VideoFailed } from '@renderer/types/video'
|
||||
import dayjs from 'dayjs'
|
||||
import { CheckCircleIcon, CircleXIcon, Clock9Icon } from 'lucide-react'
|
||||
import { useMemo, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import useSWRImmutable from 'swr/immutable'
|
||||
|
||||
export type VideoViewerProps =
|
||||
| {
|
||||
@ -41,13 +44,7 @@ export const VideoViewer = ({ video, onDownload, onRegenerate }: VideoViewerProp
|
||||
)}
|
||||
{video && video.status === 'downloading' && <DownloadingVideo progress={video.progress} />}
|
||||
{video && video.status === 'downloaded' && loadSuccess !== false && (
|
||||
<video
|
||||
controls
|
||||
className="h-full w-full"
|
||||
onLoadedData={() => setLoadSuccess(true)}
|
||||
onError={() => setLoadSuccess(false)}>
|
||||
<source src="video.mp4" type="video/mp4" />
|
||||
</video>
|
||||
<VideoPlayer video={video} setLoadSuccess={setLoadSuccess} />
|
||||
)}
|
||||
{video && video.status === 'failed' && <FailedVideo error={video.error} />}
|
||||
{video && video.status === 'downloaded' && loadSuccess === false && (
|
||||
@ -176,3 +173,36 @@ const LoadFailedVideo = ({ onRedownload }: { onRedownload: () => void }) => {
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const VideoPlayer = ({
|
||||
video,
|
||||
setLoadSuccess
|
||||
}: {
|
||||
video: VideoDownloaded
|
||||
setLoadSuccess: (value: boolean) => void
|
||||
}) => {
|
||||
const fetcher = async () => {
|
||||
const file = await FileManager.getFile(video.fileId)
|
||||
if (!file) {
|
||||
throw new Error(`Video file ${video.fileId} not exist.`)
|
||||
}
|
||||
return FileManager.getFilePath(file)
|
||||
}
|
||||
const { data: src, isLoading, error } = useSWRImmutable(`video/file/${video.id}`, fetcher)
|
||||
|
||||
if (error) {
|
||||
setLoadSuccess(false)
|
||||
}
|
||||
|
||||
return (
|
||||
<Skeleton isLoaded={!isLoading}>
|
||||
<video
|
||||
controls
|
||||
className="h-full w-full"
|
||||
onLoadedData={() => setLoadSuccess(true)}
|
||||
onError={() => setLoadSuccess(false)}>
|
||||
<source src={src} type="video/mp4" />
|
||||
</video>
|
||||
</Skeleton>
|
||||
)
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user