diff --git a/index.html b/index.html
index 5b0c741..c5aa44b 100644
--- a/index.html
+++ b/index.html
@@ -249,29 +249,33 @@
this.files.push(...newFiles);
- await processBatch(newFiles, async (fileObj) => {
+ await processBatch(newFiles, async (orig) => {
+ // Toujours muter via le proxy réactif d'Alpine
+ const f = this.files.find(x => x.id === orig.id);
+ if (!f) return;
+
// Étape 1 : HEIC → JPEG
- fileObj.status = 'converting';
+ f.status = 'converting';
try {
- fileObj.originalBlob = await convertHeicToJpeg(fileObj.originalFile);
- fileObj.originalUrl = URL.createObjectURL(fileObj.originalBlob);
+ f.originalBlob = await convertHeicToJpeg(orig.originalFile);
+ f.originalUrl = URL.createObjectURL(f.originalBlob);
} catch (e) {
- fileObj.status = 'error';
- fileObj.error = `Conversion échouée : ${e.message}`;
+ f.status = 'error';
+ f.error = `Conversion échouée : ${e.message}`;
return;
}
// Étape 2 : suppression du fond
- fileObj.status = 'processing';
+ f.status = 'processing';
try {
- fileObj.processedBlob = await processImage(
- fileObj.originalBlob, fileObj._seedColor, fileObj.tolerance
+ f.processedBlob = await processImage(
+ f.originalBlob, f._seedColor, f.tolerance
);
- fileObj.processedUrl = URL.createObjectURL(fileObj.processedBlob);
- fileObj.status = 'done';
+ f.processedUrl = URL.createObjectURL(f.processedBlob);
+ f.status = 'done';
} catch (e) {
- fileObj.status = 'error';
- fileObj.error = `Détourage échoué : ${e.message}`;
+ f.status = 'error';
+ f.error = `Détourage échoué : ${e.message}`;
}
}, 3);
},
diff --git a/js/heicConverter.js b/js/heicConverter.js
index 4971c5a..3dd9b92 100644
--- a/js/heicConverter.js
+++ b/js/heicConverter.js
@@ -3,7 +3,7 @@
* @param {File} file
* @returns {Promise}
* @throws {TypeError} si l'entrée n'est pas un fichier HEIC/HEIF
- * @throws {Error} si la conversion échoue
+ * @throws {Error} si la conversion échoue ou dépasse 30s
*/
export async function convertHeicToJpeg(file) {
if (!(file instanceof File)) {
@@ -12,18 +12,28 @@ export async function convertHeicToJpeg(file) {
// Certains iPhone envoient un type MIME vide pour les HEIC — on l'autorise
const type = file.type.toLowerCase();
if (type !== '' && !['image/heic', 'image/heif'].includes(type)) {
- throw new TypeError(`Format attendu : HEIC/HEIF. Reçu : ${file.type}`);
+ throw new TypeError(`Format attendu : HEIC/HEIF. Reçu : ${file.type || '(vide)'}`);
}
- const result = await heic2any({
+ console.log(`[heicConverter] Début conversion : ${file.name} (${file.type || 'type vide'}, ${(file.size/1024).toFixed(0)} Ko)`);
+
+ const timeout = new Promise((_, reject) =>
+ setTimeout(() => reject(new Error('Timeout : conversion > 30s. Vérifiez que le fichier est bien un HEIC valide.')), 30_000)
+ );
+
+ const conversion = heic2any({
blob: file,
toType: 'image/jpeg',
quality: 0.92,
});
+ const result = await Promise.race([conversion, timeout]);
+
const blob = Array.isArray(result) ? result[0] : result;
if (!(blob instanceof Blob)) {
throw new Error("heic2any n'a pas retourné un Blob");
}
+
+ console.log(`[heicConverter] ✅ Conversion réussie : ${file.name} → ${(blob.size/1024).toFixed(0)} Ko`);
return blob;
}