From 42a902afc64f121d6ddf2153e4ad21a8adcb8941 Mon Sep 17 00:00:00 2001 From: JotaChina Date: Thu, 26 Mar 2026 19:48:02 -0300 Subject: [PATCH] testando ui otimista --- assets/js/creations/file.js | 61 +++++++++++++++++++++++++++++++++---- 1 file changed, 55 insertions(+), 6 deletions(-) diff --git a/assets/js/creations/file.js b/assets/js/creations/file.js index 62de990b..43dc95fc 100755 --- a/assets/js/creations/file.js +++ b/assets/js/creations/file.js @@ -905,16 +905,64 @@ function downloadFile(content, fileName) { URL.revokeObjectURL(url); } +// Função para buscar os samples curtos (batidas) e guardá-los no ZIP +async function applyInstrumentsToZip(zip) { + const pathMap = getSamplePathMap(); + const tracks = appState.pattern.tracks || []; + + for (const track of tracks) { + if (track.type === "bassline") continue; // Ignora as linhas de montagem + + // Só avança se for um sampler + const isSampler = track.type === "sampler" || track.samplePath || track.filePath || track.sampleName; + if (!isSampler) continue; + + const rawSrc = track.samplePath || track.filePath || track.sampleName || track.name || ""; + if (!rawSrc) continue; + + const fileName = String(rawSrc).split(/[\\/]/).pop(); + const zipPath = `samples/${fileName}`; + + // Se já adicionamos este ficheiro no zip (ex: se usar o mesmo kick 2x), salta + if (zip.file(zipPath)) continue; + + try { + // Tenta achar a URL real do áudio no servidor + let fetchUrl = track.samplePath || track.filePath; + + // Se não tem caminho direto, tenta pelo manifest + if (!fetchUrl) { + fetchUrl = resolveSamplePath(fileName, pathMap); + } + + // Fallback final usando a sua variável SAMPLE_SRC + if (!fetchUrl) { + fetchUrl = `${SAMPLE_SRC}/${fileName}`; + } + + // Faz o download silencioso e insere no ZIP usando a sua cache + const arrayBuffer = await _fetchArrayBufferCached(fetchUrl); + zip.file(zipPath, arrayBuffer); + + } catch (err) { + console.warn(`[Export] Não foi possível incluir o sample ${fileName} no zip:`, err); + } + } +} + async function generateAndDownloadMmpz(baseName) { initializeAudioContext(); - const baseXmlString = generateXmlFromState(); // seu método atual (patterns OK) + const baseXmlString = generateXmlFromState(); const xmlDoc = new DOMParser().parseFromString(baseXmlString, "application/xml"); - // JSZip precisa existir (você já usa pra abrir mmpz) const zip = new JSZip(); + // 1. Empacota as pistas de áudio (Timeline) await applySampleTracksToXmlAndZip(xmlDoc, zip); + + // 2. 🔥 NOVO: Empacota as amostras da bateria (Kicks, Snares...) + await applyInstrumentsToZip(zip); const finalXml = new XMLSerializer().serializeToString(xmlDoc); zip.file(`${baseName}.mmp`, finalXml); @@ -926,24 +974,25 @@ async function generateAndDownloadMmpz(baseName) { const blob = await zip.generateAsync({ type: "blob", compression: "DEFLATE" }); downloadBlob(blob, `${baseName}.zip`); - } export async function buildRenderPackageBlob(baseName = "projeto") { initializeAudioContext(); - const baseXmlString = generateXmlFromState(); // patterns + const baseXmlString = generateXmlFromState(); const xmlDoc = new DOMParser().parseFromString(baseXmlString, "application/xml"); const zip = new JSZip(); - await applySampleTracksToXmlAndZip(xmlDoc, zip); // ✅ coloca sampletco + samples/*.wav + await applySampleTracksToXmlAndZip(xmlDoc, zip); + + // 🔥 NOVO: Garante que o servidor recebe os samples da bateria para a renderização final! + await applyInstrumentsToZip(zip); const finalXml = new XMLSerializer().serializeToString(xmlDoc); zip.file(`${baseName}.mmp`, finalXml); const blob = await zip.generateAsync({ type: "blob", compression: "DEFLATE" }); - // pode ser .mmpz (LMMS costuma aceitar) ou .zip (você já usa) return { blob, fileName: `${baseName}.mmpz` }; }