Spaces:
Running
Running
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' | |
} | |
} | |
}) |