mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2025-12-28 05:11:24 +08:00
feat(video): add video panel component with error handling
Implement video panel with placeholder prompt input and video display area Add error states for invalid and undefined video cases Update i18n strings for video related messages
This commit is contained in:
parent
45bdea5301
commit
ab2aa8380f
@ -4646,7 +4646,14 @@
|
||||
"title": "Update"
|
||||
},
|
||||
"video": {
|
||||
"title": "Video"
|
||||
"error": {
|
||||
"invalid": "Invalid video"
|
||||
},
|
||||
"prompt": {
|
||||
"placeholder": "describes the video to generate"
|
||||
},
|
||||
"title": "Video",
|
||||
"undefined": "No available video"
|
||||
},
|
||||
"warning": {
|
||||
"missing_provider": "The supplier does not exist; reverted to the default supplier {{provider}}. This may cause issues."
|
||||
|
||||
22
src/renderer/src/pages/video/Video.tsx
Normal file
22
src/renderer/src/pages/video/Video.tsx
Normal file
@ -0,0 +1,22 @@
|
||||
import { CircleXIcon } from 'lucide-react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
export interface VideoProps {
|
||||
video: null | undefined
|
||||
}
|
||||
|
||||
export const Video = ({ video }: VideoProps) => {
|
||||
const { t } = useTranslation()
|
||||
return (
|
||||
<div className="flex h-full w-full items-center justify-center rounded-2xl bg-foreground-200">
|
||||
{video && <video></video>}
|
||||
{video === undefined && t('video.undefined')}
|
||||
{video === null && (
|
||||
<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>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@ -7,6 +7,7 @@ import { useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
import { ProviderSetting } from './settings/ProviderSetting'
|
||||
import { VideoPanel } from './VideoPanel'
|
||||
|
||||
export const VideoPage = () => {
|
||||
const { t } = useTranslation()
|
||||
@ -21,9 +22,9 @@ export const VideoPage = () => {
|
||||
<ProviderSetting providerId={providerId} setProviderId={setProviderId} />
|
||||
</div>
|
||||
<Divider orientation="vertical" />
|
||||
<div className="flex-1 p-2"></div>
|
||||
<VideoPanel />
|
||||
<Divider orientation="vertical" />
|
||||
<div className="w-25"></div>
|
||||
<div className="w-40"></div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
39
src/renderer/src/pages/video/VideoPanel.tsx
Normal file
39
src/renderer/src/pages/video/VideoPanel.tsx
Normal file
@ -0,0 +1,39 @@
|
||||
import { Button, Skeleton, Textarea } from '@heroui/react'
|
||||
import { ArrowUp } from 'lucide-react'
|
||||
import { useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
import { Video } from './Video'
|
||||
|
||||
export const VideoPanel = () => {
|
||||
const { t } = useTranslation()
|
||||
const [prompt, setPrompt] = useState('')
|
||||
// TODO: get video job from api
|
||||
const video = { success: false, data: undefined }
|
||||
return (
|
||||
<div className="flex flex-1 flex-col p-2">
|
||||
<div className="m-8 flex-1">
|
||||
<Skeleton className="h-full w-full rounded-2xl" classNames={{ content: 'h-full w-full' }} isLoaded={true}>
|
||||
<Video video={video.data} />
|
||||
</Skeleton>
|
||||
</div>
|
||||
<div className="relative">
|
||||
<Textarea
|
||||
label={t('common.prompt')}
|
||||
placeholder={t('video.prompt.placeholder')}
|
||||
value={prompt}
|
||||
onValueChange={setPrompt}
|
||||
isClearable
|
||||
classNames={{ inputWrapper: 'pb-8' }}
|
||||
/>
|
||||
<Button
|
||||
color="primary"
|
||||
radius="full"
|
||||
startContent={<ArrowUp size={16} className="text-primary-foreground" />}
|
||||
isIconOnly
|
||||
className="absolute right-1 bottom-1 h-6 w-6 min-w-0"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user