refactor(video): improve video status update handling with ref

- Use useRef to track videos state to avoid stale closures
- Add error handling for video status updates
- Remove hardcoded openai provider check in favor of dynamic provider
This commit is contained in:
icarus 2025-10-13 13:33:12 +08:00
parent dced99ce57
commit de10a7fd6c

View File

@ -9,18 +9,21 @@ import {
setVideosAction, setVideosAction,
updateVideoAction updateVideoAction
} from '@renderer/store/video' } from '@renderer/store/video'
import { SystemProviderIds } from '@renderer/types'
import { Video } from '@renderer/types/video' import { Video } from '@renderer/types/video'
import { video } from 'notion-helper' import { useCallback, useEffect, useRef } from 'react'
import { useCallback, useEffect } from 'react'
import useSWR from 'swr' import useSWR from 'swr'
const logger = loggerService.withContext('useVideo') const logger = loggerService.withContext('useVideo')
export const useVideos = (providerId: string) => { export const useVideos = (providerId: string) => {
const videos = useAppSelector((state) => state.video.videoMap[providerId]) const videos = useAppSelector((state) => state.video.videoMap[providerId])
const videosRef = useRef(videos)
const dispatch = useAppDispatch() const dispatch = useAppDispatch()
useEffect(() => {
videosRef.current = videos
}, [videos])
const addVideo = useCallback( const addVideo = useCallback(
(video: Video) => { (video: Video) => {
if (videos && videos.every((v) => v.id !== video.id)) { if (videos && videos.every((v) => v.id !== video.id)) {
@ -65,17 +68,27 @@ export const useVideos = (providerId: string) => {
}, [setVideos, videos]) }, [setVideos, videos])
// update videos from api // update videos from api
const openai = getProviderById(SystemProviderIds.openai) // NOTE: This provider should support openai videos endpoint. No runtime check here.
const provider = getProviderById(providerId)
const fetcher = async () => { const fetcher = async () => {
if (!videos || !openai) return [] if (!videos || !provider) return []
const openaiVideos = videos.filter((v) => v.type === 'openai') const openaiVideos = videos.filter((v) => v.type === 'openai')
const jobs = openaiVideos.map((v) => retrieveVideo({ type: 'openai', videoId: v.id, provider: openai })) const jobs = openaiVideos.map((v) => retrieveVideo({ type: 'openai', videoId: v.id, provider }))
const result = await Promise.allSettled(jobs) const result = await Promise.allSettled(jobs)
return result.filter((p) => p.status === 'fulfilled').map((p) => p.value) return result.filter((p) => p.status === 'fulfilled').map((p) => p.value)
} }
const { data, isLoading, error } = useSWR('video/openai/videos', fetcher, { refreshInterval: 3000 }) const { data, error } = useSWR('video/openai/videos', fetcher, { refreshInterval: 3000 })
useEffect(() => { useEffect(() => {
logger.debug('effect', { data, videos }) if (error) {
logger.error('Failed to fetch video status updates', error)
return
}
if (!provider) {
logger.warn(`Provider ${providerId} not found.`)
return
}
const videos = videosRef.current
if (!data || !videos) return if (!data || !videos) return
data.forEach((v) => { data.forEach((v) => {
const retrievedVideo = v.video const retrievedVideo = v.video
@ -100,15 +113,9 @@ export const useVideos = (providerId: string) => {
if (storeVideo.status === 'in_progress' || storeVideo.status === 'queued') { if (storeVideo.status === 'in_progress' || storeVideo.status === 'queued') {
setVideo({ ...storeVideo, status: 'completed', thumbnail: null, metadata: retrievedVideo }) setVideo({ ...storeVideo, status: 'completed', thumbnail: null, metadata: retrievedVideo })
// try to request thumbnail here. // try to request thumbnail here.
if (!openai) {
logger.warn(
`Try to fetch thumbnail for video ${retrievedVideo.id}, but provider ${providerId} not found.`
)
return
}
retrieveVideoContent({ retrieveVideoContent({
type: 'openai', type: 'openai',
provider: openai, provider,
videoId: retrievedVideo.id, videoId: retrievedVideo.id,
query: { variant: 'thumbnail' } query: { variant: 'thumbnail' }
}) })
@ -130,7 +137,7 @@ export const useVideos = (providerId: string) => {
}) })
} }
}) })
}, [data]) }, [data, error, provider, providerId, setVideo])
return { return {
videos: videos ?? [], videos: videos ?? [],