123 lines
2.8 KiB
TypeScript
123 lines
2.8 KiB
TypeScript
import { create } from 'zustand'
|
|
|
|
export interface StoryboardFrame {
|
|
id: string
|
|
index: number
|
|
narration: string
|
|
imagePrompt: string
|
|
imagePath?: string
|
|
audioPath?: string
|
|
duration: number
|
|
order: number
|
|
}
|
|
|
|
export interface Storyboard {
|
|
id: string
|
|
title: string
|
|
frames: StoryboardFrame[]
|
|
totalDuration: number
|
|
}
|
|
|
|
interface EditorState {
|
|
storyboard: Storyboard | null
|
|
selectedFrameId: string | null
|
|
isPlaying: boolean
|
|
currentTime: number
|
|
|
|
// Actions
|
|
setStoryboard: (storyboard: Storyboard) => void
|
|
selectFrame: (frameId: string | null) => void
|
|
setSelectedFrameId: (frameId: string | null) => void // Alias for selectFrame
|
|
reorderFrames: (fromIndex: number, toIndex: number) => void
|
|
updateFrameDuration: (frameId: string, duration: number) => void
|
|
updateFrame: (frameId: string, updates: Partial<StoryboardFrame>) => void
|
|
setPlaying: (playing: boolean) => void
|
|
setCurrentTime: (time: number | ((prev: number) => number)) => void
|
|
}
|
|
|
|
export const useEditorStore = create<EditorState>((set, get) => ({
|
|
storyboard: null,
|
|
selectedFrameId: null,
|
|
isPlaying: false,
|
|
currentTime: 0,
|
|
|
|
setStoryboard: (storyboard) => set({ storyboard }),
|
|
|
|
selectFrame: (frameId) => set({ selectedFrameId: frameId }),
|
|
|
|
setSelectedFrameId: (frameId) => set({ selectedFrameId: frameId }),
|
|
|
|
reorderFrames: (fromIndex, toIndex) => {
|
|
const { storyboard } = get()
|
|
if (!storyboard) return
|
|
|
|
const frames = [...storyboard.frames]
|
|
const [removed] = frames.splice(fromIndex, 1)
|
|
frames.splice(toIndex, 0, removed)
|
|
|
|
// Update order values
|
|
const reorderedFrames = frames.map((frame, idx) => ({
|
|
...frame,
|
|
order: idx,
|
|
}))
|
|
|
|
set({
|
|
storyboard: {
|
|
...storyboard,
|
|
frames: reorderedFrames,
|
|
},
|
|
})
|
|
},
|
|
|
|
updateFrameDuration: (frameId, duration) => {
|
|
const { storyboard } = get()
|
|
if (!storyboard) return
|
|
|
|
const frames = storyboard.frames.map((frame) =>
|
|
frame.id === frameId ? { ...frame, duration } : frame
|
|
)
|
|
|
|
const totalDuration = frames.reduce((sum, f) => sum + f.duration, 0)
|
|
|
|
set({
|
|
storyboard: {
|
|
...storyboard,
|
|
frames,
|
|
totalDuration,
|
|
},
|
|
})
|
|
},
|
|
|
|
updateFrame: (frameId, updates) => {
|
|
const { storyboard } = get()
|
|
if (!storyboard) return
|
|
|
|
const frames = storyboard.frames.map((frame) =>
|
|
frame.id === frameId ? { ...frame, ...updates } : frame
|
|
)
|
|
|
|
const totalDuration = frames.reduce((sum, f) => sum + f.duration, 0)
|
|
|
|
set({
|
|
storyboard: {
|
|
...storyboard,
|
|
frames,
|
|
totalDuration,
|
|
},
|
|
})
|
|
},
|
|
|
|
setPlaying: (playing) => set({ isPlaying: playing }),
|
|
|
|
setCurrentTime: (time) => {
|
|
if (typeof time === 'function') {
|
|
const { currentTime } = get()
|
|
set({ currentTime: time(currentTime) })
|
|
} else {
|
|
set({ currentTime: time })
|
|
}
|
|
},
|
|
}))
|
|
|
|
|