stike



input.addEventListener('change', (e) => { if (e.target.files.length > 0) { selectedFile = e.target.files[0]; generateBtn.style.display = 'block'; shareWaBtn.style.display = 'none'; } });

generateBtn.addEventListener('click', async () => { if (!selectedFile) return;

generateBtn.classList.add('processing'); generateBtn.innerText = 'Generando...'; loading.style.display = 'block'; shareWaBtn.style.display = 'none';

try { // Frontend Canvas Processing for WebP (512x512 standard WA Sticker) generatedWebpBlob = await processMediaToWebp(selectedFile);

loading.style.display = 'none'; generateBtn.style.display = 'none'; generateBtn.classList.remove('processing'); generateBtn.innerText = 'Generar Sticker'; shareWaBtn.style.display = 'block'; } catch (error) { console.error("Error procesando:", error); alert("Error al generar el sticker."); loading.style.display = 'none'; generateBtn.classList.remove('processing'); } });

shareWaBtn.addEventListener('click', async () => { if (!generatedWebpBlob) return;

const file = new File([generatedWebpBlob], 'sticker.webp', { type: 'image/webp' });

// Web Share API (Nativo para móviles, salta directo a apps instaladas como WA) if (navigator.canShare && navigator.canShare({ files: [file] })) { try { await navigator.share({ files: [file], title: 'Sticker Generado', text: 'Mira este sticker' }); } catch (error) { console.log('Share cancelado o fallido', error); } } else { // Fallback web: Descarga directa si está en Desktop sin Web Share API const url = URL.createObjectURL(generatedWebpBlob); const a = document.createElement('a'); a.href = url; a.download = 'sticker.webp'; document.body.appendChild(a); a.click(); URL.revokeObjectURL(url); document.body.removeChild(a); alert("Archivo WebP descargado. Envíalo como documento en WhatsApp Web."); } });

// Core Logic: Conversión a WebP 512x512 function processMediaToWebp(file) { return new Promise((resolve, reject) => { const isVideo = file.type.startsWith('video/') || file.type === 'image/gif'; const url = URL.createObjectURL(file); const canvas = document.createElement('canvas'); canvas.width = 512; canvas.height = 512; const ctx = canvas.getContext('2d');

if (isVideo) { // Nota master: Para full exportación de frames (GIF/MP4 animado a WebP animado) pure client-side // se requiere FFmpeg.wasm. Este snippet captura el primer frame/preview sin dependencias externas. const video = document.createElement('video'); video.autoplay = true; video.muted = true; video.src = url; video.onloadeddata = () => { drawToCanvasAndResolve(video, canvas, ctx, resolve); URL.revokeObjectURL(url); }; video.onerror = reject; } else { const img = new Image(); img.onload = () => { drawToCanvasAndResolve(img, canvas, ctx, resolve); URL.revokeObjectURL(url); }; img.onerror = reject; img.src = url; } }); }

function drawToCanvasAndResolve(media, canvas, ctx, resolve) { // Lógica de aspect ratio cover (WA requiere 512x512 exacto con fondo transparente) ctx.clearRect(0, 0, canvas.width, canvas.height); const size = Math.min(media.videoWidth || media.width, media.videoHeight || media.height); const x = ((media.videoWidth || media.width) - size) / 2; const y = ((media.videoHeight || media.height) - size) / 2;

ctx.drawImage(media, x, y, size, size, 0, 0, canvas.width, canvas.height);

canvas.toBlob((blob) => resolve(blob), 'image/webp', 0.8); } });