mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2026-01-10 23:59:45 +08:00
feat(video): add error handling and loading state for video creation
handle video creation errors by showing toast notifications and prevent multiple submissions by adding a loading state
This commit is contained in:
parent
5776512bf6
commit
d80eac2fbe
@ -4649,6 +4649,7 @@
|
|||||||
},
|
},
|
||||||
"video": {
|
"video": {
|
||||||
"error": {
|
"error": {
|
||||||
|
"create": "Failed to create video",
|
||||||
"invalid": "Invalid video",
|
"invalid": "Invalid video",
|
||||||
"load": {
|
"load": {
|
||||||
"message": "Failed to load the video",
|
"message": "Failed to load the video",
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import { useAddOpenAIVideo } from '@renderer/hooks/video/useOpenAIVideos'
|
|||||||
import { createVideo } from '@renderer/services/ApiService'
|
import { createVideo } from '@renderer/services/ApiService'
|
||||||
import { Provider } from '@renderer/types'
|
import { Provider } from '@renderer/types'
|
||||||
import { Video } from '@renderer/types/video'
|
import { Video } from '@renderer/types/video'
|
||||||
|
import { getErrorMessage } from '@renderer/utils'
|
||||||
import { ArrowUp } from 'lucide-react'
|
import { ArrowUp } from 'lucide-react'
|
||||||
import { useCallback, useState } from 'react'
|
import { useCallback, useState } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
@ -20,25 +21,34 @@ const logger = loggerService.withContext('VideoPanel')
|
|||||||
export const VideoPanel = ({ provider, video }: VideoPanelProps) => {
|
export const VideoPanel = ({ provider, video }: VideoPanelProps) => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const [prompt, setPrompt] = useState('')
|
const [prompt, setPrompt] = useState('')
|
||||||
|
const [isProcessing, setIsProcessing] = useState(false)
|
||||||
const addOpenAIVideo = useAddOpenAIVideo(provider.id)
|
const addOpenAIVideo = useAddOpenAIVideo(provider.id)
|
||||||
|
|
||||||
const sendRequest = useCallback(async () => {
|
const handleCreateVideo = useCallback(async () => {
|
||||||
const result = await createVideo({
|
if (isProcessing) return
|
||||||
type: 'openai',
|
setIsProcessing(true)
|
||||||
params: {
|
try {
|
||||||
prompt
|
const result = await createVideo({
|
||||||
},
|
type: 'openai',
|
||||||
provider
|
params: {
|
||||||
})
|
prompt
|
||||||
const video = result.video
|
},
|
||||||
switch (result.type) {
|
provider
|
||||||
case 'openai':
|
})
|
||||||
addOpenAIVideo(video)
|
const video = result.video
|
||||||
break
|
switch (result.type) {
|
||||||
default:
|
case 'openai':
|
||||||
logger.error(`Invalid video type ${result.type}.`)
|
addOpenAIVideo(video)
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
logger.error(`Invalid video type ${result.type}.`)
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
window.toast.error({ title: t('video.error.create'), description: getErrorMessage(e), timeout: 5000 })
|
||||||
|
} finally {
|
||||||
|
setIsProcessing(false)
|
||||||
}
|
}
|
||||||
}, [addOpenAIVideo, prompt, provider])
|
}, [addOpenAIVideo, isProcessing, prompt, provider, t])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-1 flex-col p-2">
|
<div className="flex flex-1 flex-col p-2">
|
||||||
@ -54,21 +64,23 @@ export const VideoPanel = ({ provider, video }: VideoPanelProps) => {
|
|||||||
value={prompt}
|
value={prompt}
|
||||||
onValueChange={setPrompt}
|
onValueChange={setPrompt}
|
||||||
isClearable
|
isClearable
|
||||||
|
isDisabled={isProcessing}
|
||||||
classNames={{ inputWrapper: 'pb-8' }}
|
classNames={{ inputWrapper: 'pb-8' }}
|
||||||
onKeyDown={(e: React.KeyboardEvent) => {
|
onKeyDown={(e: React.KeyboardEvent) => {
|
||||||
if (e.key === 'Enter') {
|
if (e.key === 'Enter') {
|
||||||
e.stopPropagation()
|
e.preventDefault()
|
||||||
sendRequest()
|
handleCreateVideo()
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Button
|
<Button
|
||||||
color="primary"
|
color="primary"
|
||||||
radius="full"
|
radius="full"
|
||||||
startContent={<ArrowUp size={16} className="text-primary-foreground" />}
|
|
||||||
isIconOnly
|
isIconOnly
|
||||||
className="absolute right-1 bottom-1 h-6 w-6 min-w-0"
|
isLoading={isProcessing}
|
||||||
/>
|
className="absolute right-2 bottom-2 h-6 w-6 min-w-0">
|
||||||
|
<ArrowUp size={16} className="text-primary-foreground" />
|
||||||
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user