feat(video): add video store module and migration

- Initialize video store module with state management for video operations
- Add video state to root reducer
- Extend video types with id field and specific OpenAIVideo types
- Include video store in migration to initialize videoMap
This commit is contained in:
icarus 2025-10-12 01:50:33 +08:00
parent 9487eaf091
commit 590d69cfba
4 changed files with 72 additions and 1 deletions

View File

@ -30,6 +30,7 @@ import settings from './settings'
import shortcuts from './shortcuts'
import tabs from './tabs'
import translate from './translate'
import video from './video'
import websearch from './websearch'
const logger = loggerService.withContext('Store')
@ -58,7 +59,8 @@ const rootReducer = combineReducers({
inputTools: inputToolsReducer,
translate,
ocr,
note
note,
video
})
const persistedReducer = persistReducer(

View File

@ -2662,6 +2662,7 @@ const migrateConfig = {
state.settings.sidebarIcons.visible = [...state.settings.sidebarIcons.visible, 'video']
}
}
state.video.videoMap = {}
return state
} catch (error) {
logger.error('migrate 161 error', error as Error)

View File

@ -0,0 +1,60 @@
import { loggerService } from '@logger'
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
import { Video } from '@renderer/types/video'
const logger = loggerService.withContext('Store:paintings')
export interface VideoState {
/** Provider ID to videos */
videoMap: Record<string, Video[]>
}
const initialState: VideoState = {
videoMap: {}
}
const videoSlice = createSlice({
name: 'video',
initialState,
reducers: {
addVideo: (state: VideoState, action: PayloadAction<{ providerId: string; video: Video }>) => {
const { providerId, video } = action.payload
if (state[providerId]) {
state.videoMap[providerId].unshift(video)
} else {
state.videoMap[providerId] = [video]
}
},
removeVideo: (state: VideoState, action: PayloadAction<{ providerId: string; videoId: string }>) => {
const { providerId, videoId } = action.payload
const videos = state.videoMap[providerId]
state.videoMap[providerId] = videos?.filter((c) => c.id !== videoId)
},
updateVideo: (
state: VideoState,
action: PayloadAction<{ providerId: string; update: Partial<Video> & { id: string } }>
) => {
const { providerId, update } = action.payload
const existingIndex = state.videoMap[providerId].findIndex((c) => c.id === update.id)
if (existingIndex !== -1) {
state.videoMap[providerId] = state.videoMap[providerId]?.map((c) => (c.id === update.id ? { ...c, update } : c))
} else {
logger.error(`Video with id ${update.id} not found in ${providerId}`)
}
},
setVideos: (state: VideoState, action: PayloadAction<{ providerId: string; videos: Video[] }>) => {
const { providerId, videos } = action.payload
state.videoMap[providerId] = videos
}
}
})
export const {
addVideo: addVideoAction,
removeVideo: removeVideoAction,
updateVideo: updateVideoAction,
setVideos: setVideosAction
} = videoSlice.actions
export default videoSlice.reducer

View File

@ -7,6 +7,7 @@ export type VideoEndpointType = 'openai'
export type VideoStatus = 'queued' | 'in_progress' | 'completed' | 'failed'
interface VideoBase {
id: string
type: VideoEndpointType
status: VideoStatus
}
@ -34,10 +35,17 @@ export interface VideoFailed extends VideoBase {
error: unknown
}
export interface OpenAIVideoQueued extends VideoQueued, OpenAIVideoBase {}
export interface OpenAIVideoInProgress extends VideoInProgress, OpenAIVideoBase {}
export interface OpenAIVideoCompleted extends VideoCompleted, OpenAIVideoBase {}
export interface OpenAIVideoFailed extends VideoFailed, OpenAIVideoBase {
error: OpenAI.Videos.Video['error']
}
export type OpenAIVideo = OpenAIVideoQueued | OpenAIVideoInProgress | OpenAIVideoCompleted | OpenAIVideoFailed
export type Video = OpenAIVideo
// Create Video
interface CreateVideoBaseParams {
type: VideoEndpointType