2nzi's picture
first commit
2964111 verified
import { defineStore } from 'pinia'
export const useUploadStore = defineStore('upload', {
state: () => ({
selectedFile: null,
fileType: null, // 'image' ou 'video'
filePreview: null,
uploadStatus: 'idle', // 'idle', 'uploading', 'success', 'error'
error: null,
// Spécifique aux vidéos
videoType: null, // 'static' ou 'dynamic'
extractedFrame: null // Pour les vidéos statiques
}),
getters: {
isFileSelected: (state) => state.selectedFile !== null,
isImage: (state) => state.fileType === 'image',
isVideo: (state) => state.fileType === 'video',
isUploading: (state) => state.uploadStatus === 'uploading',
// Nouveaux getters pour les vidéos
isStaticVideo: (state) => state.fileType === 'video' && state.videoType === 'static',
isDynamicVideo: (state) => state.fileType === 'video' && state.videoType === 'dynamic',
shouldProcessDirectly: (state) => state.fileType === 'image' || state.isStaticVideo,
needsParameters: (state) => state.isDynamicVideo
},
actions: {
setFile(file) {
this.selectedFile = file
this.fileType = file.type.startsWith('image/') ? 'image' : 'video'
this.createPreview(file)
this.uploadStatus = 'idle'
this.error = null
// Reset video-specific data
this.videoType = null
this.extractedFrame = null
},
async setVideoType(type) {
this.videoType = type
if (type === 'static') {
console.log('🔥 Starting frame extraction for static video...')
await this.extractFrameFromVideo()
console.log('🔥 Frame extraction completed:', {
hasExtractedFrame: !!this.extractedFrame,
extractedFrameType: this.extractedFrame?.type,
extractedFrameName: this.extractedFrame?.name
})
}
},
createPreview(file) {
if (file.type.startsWith('image/')) {
this.filePreview = URL.createObjectURL(file)
} else {
this.filePreview = URL.createObjectURL(file)
}
},
async extractFrameFromVideo() {
if (!this.selectedFile || !this.isVideo) {
console.error('🔥 Cannot extract frame: no file or not a video')
return null
}
try {
const video = document.createElement('video')
video.src = URL.createObjectURL(this.selectedFile)
return new Promise((resolve, reject) => {
video.addEventListener('loadedmetadata', () => {
console.log('🔥 Video metadata loaded, seeking to frame 0')
video.currentTime = 0 // Première image
})
video.addEventListener('seeked', () => {
try {
console.log('🔥 Video seeked, drawing to canvas')
const canvas = document.createElement('canvas')
canvas.width = video.videoWidth
canvas.height = video.videoHeight
if (video.videoWidth === 0 || video.videoHeight === 0) {
throw new Error('Video dimensions are 0')
}
const ctx = canvas.getContext('2d')
ctx.drawImage(video, 0, 0)
canvas.toBlob((blob) => {
if (!blob) {
reject(new Error('Failed to create blob from canvas'))
return
}
// Créer un File avec un nom au lieu d'un Blob simple
const file = new File([blob], 'extracted_frame.jpg', { type: 'image/jpeg' })
this.extractedFrame = file
console.log('🔥 Frame extracted successfully:', {
name: file.name,
type: file.type,
size: file.size
})
URL.revokeObjectURL(video.src)
resolve(file)
}, 'image/jpeg', 0.9)
} catch (err) {
console.error('🔥 Error during canvas operations:', err)
URL.revokeObjectURL(video.src)
reject(err)
}
})
video.addEventListener('error', (err) => {
console.error('🔥 Video loading error:', err)
URL.revokeObjectURL(video.src)
reject(err)
})
// Timeout de sécurité
setTimeout(() => {
console.error('🔥 Frame extraction timeout')
URL.revokeObjectURL(video.src)
reject(new Error('Frame extraction timeout'))
}, 10000)
})
} catch (error) {
console.error('🔥 Erreur extraction frame:', error)
this.setError('Impossible d\'extraire une image de la vidéo: ' + error.message)
return null
}
},
clearFile() {
if (this.filePreview) {
URL.revokeObjectURL(this.filePreview)
}
this.selectedFile = null
this.fileType = null
this.filePreview = null
this.uploadStatus = 'idle'
this.error = null
this.videoType = null
this.extractedFrame = null
},
setUploadStatus(status) {
this.uploadStatus = status
},
setError(error) {
this.error = error
this.uploadStatus = 'error'
}
}
})