/** * Project Store * Manages project state and operations */ import { create } from 'zustand' import { ProjectInfo, VideoTrack, AudioTrack } from '../services/tauri' import { ProjectService } from '../services/tauri' interface ProjectState { // Current project currentProject: ProjectInfo | null // Project list projects: ProjectInfo[] // Loading states isLoading: boolean isSaving: boolean // Error state error: string | null // Actions createProject: (name: string, description?: string) => Promise loadProject: (projectPath: string) => Promise saveProject: () => Promise closeProject: () => void // Track management addVideoTrack: (track: VideoTrack) => void addAudioTrack: (track: AudioTrack) => void removeVideoTrack: (trackId: string) => void removeAudioTrack: (trackId: string) => void updateVideoTrack: (trackId: string, updates: Partial) => void updateAudioTrack: (trackId: string, updates: Partial) => void // Timeline management setTimelinePosition: (position: number) => void setTimelineZoom: (zoom: number) => void setTimelineDuration: (duration: number) => void // Utility actions setError: (error: string | null) => void clearError: () => void } export const useProjectStore = create((set, get) => ({ // Initial state currentProject: null, projects: [], isLoading: false, isSaving: false, error: null, // Project operations createProject: async (name: string, description = '') => { set({ isLoading: true, error: null }) try { const project = await ProjectService.createProject(name, description) set({ currentProject: project, isLoading: false }) } catch (error) { set({ error: error instanceof Error ? error.message : 'Failed to create project', isLoading: false }) } }, loadProject: async (projectPath: string) => { set({ isLoading: true, error: null }) try { const project = await ProjectService.loadProject(projectPath) set({ currentProject: project, isLoading: false }) } catch (error) { set({ error: error instanceof Error ? error.message : 'Failed to load project', isLoading: false }) } }, saveProject: async () => { const { currentProject } = get() if (!currentProject) return set({ isSaving: true, error: null }) try { await ProjectService.saveProject(currentProject) set({ currentProject: { ...currentProject, modified_at: new Date().toISOString() }, isSaving: false }) } catch (error) { set({ error: error instanceof Error ? error.message : 'Failed to save project', isSaving: false }) } }, closeProject: () => { set({ currentProject: null }) }, // Track management addVideoTrack: (track: VideoTrack) => { const { currentProject } = get() if (!currentProject) return const updatedProject = { ...currentProject, video_tracks: [...currentProject.video_tracks, track], modified_at: new Date().toISOString() } set({ currentProject: updatedProject }) }, addAudioTrack: (track: AudioTrack) => { const { currentProject } = get() if (!currentProject) return const updatedProject = { ...currentProject, audio_tracks: [...currentProject.audio_tracks, track], modified_at: new Date().toISOString() } set({ currentProject: updatedProject }) }, removeVideoTrack: (trackId: string) => { const { currentProject } = get() if (!currentProject) return const updatedProject = { ...currentProject, video_tracks: currentProject.video_tracks.filter(track => track.id !== trackId), modified_at: new Date().toISOString() } set({ currentProject: updatedProject }) }, removeAudioTrack: (trackId: string) => { const { currentProject } = get() if (!currentProject) return const updatedProject = { ...currentProject, audio_tracks: currentProject.audio_tracks.filter(track => track.id !== trackId), modified_at: new Date().toISOString() } set({ currentProject: updatedProject }) }, updateVideoTrack: (trackId: string, updates: Partial) => { const { currentProject } = get() if (!currentProject) return const updatedProject = { ...currentProject, video_tracks: currentProject.video_tracks.map(track => track.id === trackId ? { ...track, ...updates } : track ), modified_at: new Date().toISOString() } set({ currentProject: updatedProject }) }, updateAudioTrack: (trackId: string, updates: Partial) => { const { currentProject } = get() if (!currentProject) return const updatedProject = { ...currentProject, audio_tracks: currentProject.audio_tracks.map(track => track.id === trackId ? { ...track, ...updates } : track ), modified_at: new Date().toISOString() } set({ currentProject: updatedProject }) }, // Timeline management setTimelinePosition: (position: number) => { const { currentProject } = get() if (!currentProject) return const updatedProject = { ...currentProject, timeline: { ...currentProject.timeline, position } } set({ currentProject: updatedProject }) }, setTimelineZoom: (zoom: number) => { const { currentProject } = get() if (!currentProject) return const updatedProject = { ...currentProject, timeline: { ...currentProject.timeline, zoom } } set({ currentProject: updatedProject }) }, setTimelineDuration: (duration: number) => { const { currentProject } = get() if (!currentProject) return const updatedProject = { ...currentProject, timeline: { ...currentProject.timeline, duration } } set({ currentProject: updatedProject }) }, // Utility actions setError: (error: string | null) => { set({ error }) }, clearError: () => { set({ error: null }) } })) // Selectors for easier access to specific state export const useCurrentProject = () => useProjectStore(state => state.currentProject) export const useProjectLoading = () => useProjectStore(state => state.isLoading) export const useProjectSaving = () => useProjectStore(state => state.isSaving) export const useProjectError = () => useProjectStore(state => state.error) export const useVideoTracks = () => useProjectStore(state => state.currentProject?.video_tracks || []) export const useAudioTracks = () => useProjectStore(state => state.currentProject?.audio_tracks || []) export const useTimeline = () => useProjectStore(state => state.currentProject?.timeline || { duration: 0, zoom: 1, position: 0 })