From 6bb8cb8dad8ace70d8a94efe213fa5415d20fa25 Mon Sep 17 00:00:00 2001 From: JotaChina Date: Sat, 27 Dec 2025 13:51:27 -0300 Subject: [PATCH] editando e enviando patterns na playlist --- assets/js/creations/audio/audio_ui.js | 117 ++++++++++---------------- 1 file changed, 46 insertions(+), 71 deletions(-) diff --git a/assets/js/creations/audio/audio_ui.js b/assets/js/creations/audio/audio_ui.js index 5c956f49..42967706 100755 --- a/assets/js/creations/audio/audio_ui.js +++ b/assets/js/creations/audio/audio_ui.js @@ -188,14 +188,9 @@ export function renderAudioEditor() { if (!audioEditor || !existingTrackContainer) return; - // ✅ preserva a posição de scroll mesmo recriando o container - const prevScrollLeft = - (existingTrackContainer?.scrollLeft ?? 0) || - (appState.audio?.editorScrollLeft ?? 0); - - const prevScrollTop = - (existingTrackContainer?.scrollTop ?? 0) || - (appState.audio?.editorScrollTop ?? 0); + // ✅ Salva o scroll atual (senão toda edição “pula” pro início) + const prevScrollLeft = existingTrackContainer.scrollLeft || 0; + const prevScrollTop = existingTrackContainer.scrollTop || 0; _ensureGlobalPlaylistSelectionFields(); _installPlaylistKeybindOnce(); @@ -203,13 +198,6 @@ export function renderAudioEditor() { // --- Identifica o pai real do container --- const tracksParent = existingTrackContainer.parentElement; - // ✅ NÃO recria o container (preserva scroll e evita “voltar pro início”) - const newTrackContainer = existingTrackContainer; - const scrollEl = newTrackContainer; - - // ✅ limpa apenas as lanes antigas (mantém o scroller) - newTrackContainer.innerHTML = ""; - // --- CRIAÇÃO E RENDERIZAÇÃO DA RÉGUA --- let rulerWrapper = tracksParent.querySelector(".ruler-wrapper"); @@ -438,6 +426,12 @@ export function renderAudioEditor() { menu.style.top = `${e.clientY}px`; }); + // Recriação Container Pistas + const newTrackContainer = existingTrackContainer.cloneNode(false); + tracksParent.replaceChild(newTrackContainer, existingTrackContainer); + // ✅ único scroller horizontal/vertical do editor + const scrollEl = newTrackContainer; // #audio-track-container + // === RENDERIZAÇÃO DAS PISTAS (LANES) === // CORREÇÃO: Junta as pistas de áudio com as Basslines (que estão no Pattern State) @@ -783,49 +777,35 @@ export function renderAudioEditor() { .forEach((g) => (g.style.width = `${widthPx}px`)); } - // Sync Scroll (rebinding para não acumular listeners a cada render) - newTrackContainer.addEventListener("scroll", () => { - if (newTrackContainer.__onScroll) { - newTrackContainer.removeEventListener("scroll", newTrackContainer.__onScroll); + // Sync Scroll + newTrackContainer.addEventListener("scroll", () => { + const scrollPos = scrollEl.scrollLeft; + + // sincroniza régua com o container + const mainRuler = tracksParent.querySelector(".timeline-ruler"); + if (mainRuler && mainRuler.scrollLeft !== scrollPos) { + mainRuler.scrollLeft = scrollPos; } - newTrackContainer.__onScroll = () => { - const scrollPos = scrollEl.scrollLeft; + // expansão "infinita" + const threshold = 300; + const rightEdge = scrollPos + newTrackContainer.clientWidth; + const currentWidth = appState.audio.timelineWidthPx || totalWidth; - // guarda no estado - appState.audio.editorScrollLeft = scrollPos; - appState.audio.editorScrollTop = scrollEl.scrollTop || 0; + if (rightEdge > currentWidth - threshold) { + const newWidth = Math.ceil(currentWidth * 1.5); - // sincroniza régua com o container - const mainRuler = tracksParent.querySelector(".timeline-ruler"); - if (mainRuler && mainRuler.scrollLeft !== scrollPos) { - mainRuler.scrollLeft = scrollPos; - } + applyTimelineWidth(newWidth); - // expansão "infinita" - const threshold = 300; - const rightEdge = scrollPos + newTrackContainer.clientWidth; - const currentWidth = appState.audio.timelineWidthPx || totalWidth; - - if (rightEdge > currentWidth - threshold) { - const newWidth = Math.ceil(currentWidth * 1.5); - - applyTimelineWidth(newWidth); - - const rulerEl = tracksParent.querySelector(".timeline-ruler"); - appendRulerMarkers(rulerEl, currentWidth, newWidth, barWidthPx); - } - }; - newTrackContainer.addEventListener("scroll", newTrackContainer.__onScroll); + const rulerEl = tracksParent.querySelector(".timeline-ruler"); + appendRulerMarkers(rulerEl, currentWidth, newWidth, barWidthPx); + } }); - // Event Listener Principal (mousedown) - rebinding - if (newTrackContainer.__onMouseDown) { - newTrackContainer.removeEventListener("mousedown", newTrackContainer.__onMouseDown); - } + // Event Listener Principal (mousedown) - newTrackContainer.__onMouseDown = (e) => { + newTrackContainer.addEventListener("mousedown", (e) => { document.getElementById("timeline-context-menu").style.display = "none"; document.getElementById("ruler-context-menu").style.display = "none"; @@ -1318,16 +1298,10 @@ export function renderAudioEditor() { document.addEventListener("mousemove", onMouseMoveSeek); document.addEventListener("mouseup", onMouseUpSeek); } - }; - - newTrackContainer.addEventListener("mousedown", newTrackContainer.__onMouseDown); + }); // Menu Contexto Pista - if (newTrackContainer.__onContextMenu) { - newTrackContainer.removeEventListener("contextmenu", newTrackContainer.__onContextMenu); - } - - newTrackContainer.__onContextMenu = (e) => { + newTrackContainer.addEventListener("contextmenu", (e) => { e.preventDefault(); document.getElementById("ruler-context-menu").style.display = "none"; const menu = document.getElementById("timeline-context-menu"); @@ -1399,22 +1373,23 @@ export function renderAudioEditor() { menu.style.display = "none"; } } - }; - - newTrackContainer.addEventListener("contextmenu", newTrackContainer.__onContextMenu); - - // ✅ restaura scroll após reconstruir a DOM (precisa ser após tudo estar no DOM) - requestAnimationFrame(() => { - try { - newTrackContainer.scrollLeft = prevScrollLeft; - newTrackContainer.scrollTop = prevScrollTop; - - // mantém régua alinhada na mesma posição - const mainRuler = tracksParent.querySelector(".timeline-ruler"); - if (mainRuler) mainRuler.scrollLeft = prevScrollLeft; - } catch {} }); + + // ✅ Restaura o scroll anterior após reconstruir o container + // (evita “voltar pro início” depois de mover/redimensionar/deletar) + try { + newTrackContainer.scrollLeft = prevScrollLeft; + newTrackContainer.scrollTop = prevScrollTop; + + // mantém régua alinhada (caso ela suporte scrollLeft) + const mainRuler = tracksParent.querySelector(".timeline-ruler"); + if (mainRuler) mainRuler.scrollLeft = prevScrollLeft; + } catch (err) { + // silencioso: não pode quebrar a DAW + } } + + export function updateAudioEditorUI() { const playBtn = document.getElementById("audio-editor-play-btn"); if (!playBtn) return;