versão 2.0.1 - Correção do grid (Editor de Samples), loop, delete, resize, trim e streching funcionais

This commit is contained in:
JotaChina committed 2025-10-22 19:21:51 -03:00
1 parent 352ceecec8
commit b3f0d13b90
9 files changed
+856 -250

No files matched your search

+103 -31
View File
@@ -1,7 +1,8 @@
// js/main.js
import { appState, resetProjectState } from "./state.js";
import { addTrackToState, removeLastTrackFromState } from "./pattern/pattern_state.js";
import { addAudioTrackLane } from "./audio/audio_state.js";
// --- CORREÇÃO AQUI ---
import { addAudioTrackLane, removeAudioClip } from "./audio/audio_state.js";
import { updateTransportLoop } from "./audio/audio_audio.js";
import {
togglePlayback,
@@ -20,6 +21,21 @@ import { renderAudioEditor } from "./audio/audio_ui.js";
import { adjustValue, enforceNumericInput } from "./utils.js";
import { ZOOM_LEVELS } from "./config.js";
// --- NOVA FUNÇÃO ---
// Atualiza a aparência dos botões de ferramenta
function updateToolButtons() {
const sliceToolBtn = document.getElementById("slice-tool-btn");
const trimToolBtn = document.getElementById("resize-tool-trim");
const stretchToolBtn = document.getElementById("resize-tool-stretch");
if(sliceToolBtn) sliceToolBtn.classList.toggle("active", appState.global.sliceToolActive);
if(trimToolBtn) trimToolBtn.classList.toggle("active", !appState.global.sliceToolActive && appState.global.resizeMode === 'trim');
if(stretchToolBtn) stretchToolBtn.classList.toggle("active", !appState.global.sliceToolActive && appState.global.resizeMode === 'stretch');
// Desativa a ferramenta de corte se outra for selecionada
document.body.classList.toggle("slice-tool-active", appState.global.sliceToolActive);
}
document.addEventListener("DOMContentLoaded", () => {
const newProjectBtn = document.getElementById("new-project-btn");
const openMmpBtn = document.getElementById("open-mmp-btn");
@@ -36,6 +52,11 @@ document.addEventListener("DOMContentLoaded", () => {
const rewindBtn = document.getElementById("rewind-btn");
const metronomeBtn = document.getElementById("metronome-btn");
const sliceToolBtn = document.getElementById("slice-tool-btn");
// --- NOVOS BOTÕES ---
const resizeToolTrimBtn = document.getElementById("resize-tool-trim");
const resizeToolStretchBtn = document.getElementById("resize-tool-stretch");
const mmpFileInput = document.getElementById("mmp-file-input");
const sampleFileInput = document.getElementById("sample-file-input");
const openProjectModal = document.getElementById("open-project-modal");
@@ -46,6 +67,55 @@ document.addEventListener("DOMContentLoaded", () => {
const zoomInBtn = document.getElementById("zoom-in-btn");
const zoomOutBtn = document.getElementById("zoom-out-btn");
// --- LISTENERS ADICIONADOS (COM LÓGICA DE CONTROLLER) ---
// Listener para o botão "Excluir Clipe" no menu de contexto
const deleteClipBtn = document.getElementById('delete-clip');
if (deleteClipBtn) {
deleteClipBtn.addEventListener('click', () => {
const clipId = appState.global.selectedClipId; // 1. Lê o estado
if (clipId) {
if (removeAudioClip(clipId)) { // 2. Chama a função de state
appState.global.selectedClipId = null; // 3. Atualiza o estado global
renderAudioEditor(); // 4. Renderiza a mudança
}
}
// Esconde o menu
const menu = document.getElementById('timeline-context-menu');
if (menu) menu.style.display = 'none';
});
}
// Listener global para a tecla Delete/Backspace
document.addEventListener('keydown', (e) => {
// Ignora se estiver digitando em um input
if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA') {
return;
}
const clipId = appState.global.selectedClipId; // 1. Lê o estado
// Verifica se há um clipe selecionado e a tecla pressionada é Delete ou Backspace
if ((e.key === 'Delete' || e.key === 'Backspace') && clipId) {
e.preventDefault(); // Impede o navegador de voltar a página (ação do Backspace)
if (removeAudioClip(clipId)) { // 2. Chama a função de state
appState.global.selectedClipId = null; // 3. Atualiza o estado global
renderAudioEditor(); // 4. Renderiza a mudança
}
}
});
// Listener global para fechar menu de contexto ou desselecionar clipe
document.addEventListener('click', (e) => {
// Esconde o menu de contexto se clicar fora dele
const menu = document.getElementById('timeline-context-menu');
if (menu && !e.target.closest('#timeline-context-menu')) {
menu.style.display = 'none';
}
});
// --- FIM DOS LISTENERS ADICIONADOS ---
newProjectBtn.addEventListener("click", () => {
if ((appState.pattern.tracks.length > 0 || appState.audio.clips.length > 0) && !confirm("Você tem certeza? Alterações não salvas serão perdidas.")) return;
resetProjectState();
@@ -74,10 +144,31 @@ document.addEventListener("DOMContentLoaded", () => {
stopBtn.addEventListener("click", stopPlayback);
rewindBtn.addEventListener("click", rewindPlayback);
metronomeBtn.addEventListener("click", () => { initializeAudioContext(); appState.global.metronomeEnabled = !appState.global.metronomeEnabled; metronomeBtn.classList.toggle("active", appState.global.metronomeEnabled); });
if(sliceToolBtn) { sliceToolBtn.addEventListener("click", () => { appState.global.sliceToolActive = !appState.global.sliceToolActive; sliceToolBtn.classList.toggle("active", appState.global.sliceToolActive); document.body.classList.toggle("slice-tool-active", appState.global.sliceToolActive); }); }
// --- LISTENERS DE FERRAMENTAS ATUALIZADOS ---
if(sliceToolBtn) {
sliceToolBtn.addEventListener("click", () => {
appState.global.sliceToolActive = !appState.global.sliceToolActive;
updateToolButtons();
});
}
if(resizeToolTrimBtn) {
resizeToolTrimBtn.addEventListener("click", () => {
appState.global.resizeMode = 'trim';
appState.global.sliceToolActive = false;
updateToolButtons();
});
}
if(resizeToolStretchBtn) {
resizeToolStretchBtn.addEventListener("click", () => {
appState.global.resizeMode = 'stretch';
appState.global.sliceToolActive = false;
updateToolButtons();
});
}
openModalCloseBtn.addEventListener("click", closeOpenProjectModal);
// ### CORREÇÃO 2: Adicionada verificação 'if (icon)' ###
sidebarToggle.addEventListener("click", () => {
document.body.classList.toggle("sidebar-hidden");
const icon = sidebarToggle.querySelector("i");
@@ -116,50 +207,31 @@ document.addEventListener("DOMContentLoaded", () => {
});
}
audioEditorPlayBtn.addEventListener("click", () => { if (appState.global.isAudioEditorPlaying) { stopAudioEditorPlayback(); } else { startAudioEditorPlayback(); } });
audioEditorStopBtn.addEventListener("click", stopAudioEditorPlayback);
audioEditorPlayBtn.addEventListener("click", () => {
if (appState.global.isAudioEditorPlaying) {
stopAudioEditorPlayback(false); // Pausa
} else {
startAudioEditorPlayback();
}
});
audioEditorStopBtn.addEventListener("click", () => stopAudioEditorPlayback(true)); // Stop (rebobina)
// ### CORREÇÃO 1: Listeners duplicados combinados em um só ###
// No main.js
audioEditorLoopBtn.addEventListener("click", () => {
console.log("--- Botão de Loop Clicado ---"); // DEBUG 1
// 1. Altera o estado global de loop
appState.global.isLoopActive = !appState.global.isLoopActive;
console.log("Estado appState.global.isLoopActive:", appState.global.isLoopActive); // DEBUG 2
// 2. Sincroniza o estado do loop do editor
appState.audio.isAudioEditorLoopEnabled = appState.global.isLoopActive;
// 3. Atualiza a aparência do botão
audioEditorLoopBtn.classList.toggle("active", appState.global.isLoopActive);
// 4. Sincroniza o Tone.Transport
updateTransportLoop();
// 5. Mostra/esconde a área de loop
const loopArea = document.getElementById("loop-region");
// ESTE É O TESTE MAIS IMPORTANTE:
if (loopArea) {
console.log("Elemento #loop-region ENCONTRADO. Alterando classe 'visible'."); // DEBUG 3
loopArea.classList.toggle("visible", appState.global.isLoopActive);
} else {
console.error("ERRO GRAVE: Elemento #loop-region NÃO FOI ENCONTRADO!"); // DEBUG 4
}
// 6. Reinicia o playback se estiver tocando
restartAudioEditorIfPlaying();
});
if (addAudioTrackBtn) { addAudioTrackBtn.addEventListener("click", () => { addAudioTrackLane(); renderAudioEditor(); }); }
// ### CORREÇÃO 3: Ordem de execução corrigida ###
// 1. Carrega o conteúdo do navegador de samples
loadAndRenderSampleBrowser();
// 2. Adiciona o listener DEPOIS que o conteúdo supostamente existe
const browserContent = document.getElementById('browser-content');
if (browserContent) {
browserContent.addEventListener('click', function(event) {
@@ -171,6 +243,6 @@ document.addEventListener("DOMContentLoaded", () => {
});
}
// 3. Renderiza o resto
renderAll();
updateToolButtons(); // Define o estado inicial dos botões
});