// js/pattern_ui.js import { appState } from "../state.js"; import {     updateTrackSample } from "./pattern_state.js"; import { playSample, stopPlayback } from "./pattern_audio.js"; import { getTotalSteps } from "../utils.js"; import { sendAction } from '../socket.js'; import { initializeAudioContext } from '../audio.js'; // Função principal de renderização para o editor de patterns export function renderPatternEditor() {   const trackContainer = document.getElementById("track-container");   trackContainer.innerHTML = ""; // (V7) Adicionado 'trackIndex'   appState.pattern.tracks.forEach((trackData, trackIndex) => {     const trackLane = document.createElement("div");     trackLane.className = "track-lane";     trackLane.dataset.trackIndex = trackIndex; // (V7) Usando índice     if (trackData.id === appState.pattern.activeTrackId) {         trackLane.classList.add('active-track');     }     trackLane.innerHTML = `      
               
        ${trackData.name}      
     
       
         
          VOL        
       
         
          PAN        
     
     
    `; // (Listener de clique da track é local, sem mudanças)     trackLane.addEventListener('click', () => {         if (appState.pattern.activeTrackId === trackData.id) return;         stopPlayback();         appState.pattern.activeTrackId = trackData.id;         document.querySelectorAll('.track-lane').forEach(lane => lane.classList.remove('active-track'));         trackLane.classList.add('active-track');         updateGlobalPatternSelector();         redrawSequencer();     });     trackLane.addEventListener("dragover", (e) => { e.preventDefault(); trackLane.classList.add("drag-over"); });     trackLane.addEventListener("dragleave", () => trackLane.classList.remove("drag-over")); // (V9) Listener de "drop" (arrastar) agora usa 'sendAction'     trackLane.addEventListener("drop", (e) => {       e.preventDefault();       trackLane.classList.remove("drag-over");       const filePath = e.dataTransfer.getData("text/plain");             if (filePath) { sendAction({ type: 'SET_TRACK_SAMPLE', trackIndex: trackIndex, filePath: filePath });       }     });     trackContainer.appendChild(trackLane);   });     updateGlobalPatternSelector();   redrawSequencer(); } export function redrawSequencer() {   const totalGridSteps = getTotalSteps();   document.querySelectorAll(".step-sequencer-wrapper").forEach((wrapper) => {     let sequencerContainer = wrapper.querySelector(".step-sequencer");     if (!sequencerContainer) {       sequencerContainer = document.createElement("div");       sequencerContainer.className = "step-sequencer";       wrapper.appendChild(sequencerContainer);     }         const parentTrackElement = wrapper.closest(".track-lane");     const trackIndex = parseInt(parentTrackElement.dataset.trackIndex, 10); // (V7)     // ... dentro da função redrawSequencer() ...     const trackData = appState.pattern.tracks[trackIndex];     if (!trackData || !trackData.patterns || trackData.patterns.length === 0) {       sequencerContainer.innerHTML = ""; return;     } // --- CORRIJA ESTAS DUAS LINHAS --- // ANTES: // const activePatternIndex = appState.pattern.activePatternIndex; // const activePattern = trackData.patterns[activePatternIndex]; // // DEPOIS:     const activePatternIndex = trackData.activePatternIndex;     const activePattern = trackData.patterns[activePatternIndex];     if (!activePattern) {         sequencerContainer.innerHTML = ""; return;     } // ... resto da função ...     const patternSteps = activePattern.steps;     sequencerContainer.innerHTML = "";     for (let i = 0; i < totalGridSteps; i++) {       const stepWrapper = document.createElement("div");       stepWrapper.className = "step-wrapper";       const stepElement = document.createElement("div");       stepElement.className = "step";             if (patternSteps[i] === true) {         stepElement.classList.add("active");       }       stepElement.addEventListener("click", () => { initializeAudioContext(); // (V8) const currentState = activePattern.steps[i] || false; const isActive = !currentState; sendAction({ // (V7) type: 'TOGGLE_NOTE', trackIndex: trackIndex, patternIndex: activePatternIndex, stepIndex: i, isActive: isActive });         if (isActive && trackData && trackData.samplePath) {           playSample(trackData.samplePath, trackData.id);         }       });       const beatsPerBar = parseInt(document.getElementById("compasso-a-input").value, 10) || 4;       const groupIndex = Math.floor(i / beatsPerBar);       if (groupIndex % 2 === 0) {         stepElement.classList.add("step-dark");       }       const stepsPerBar = 16;       if (i > 0 && i % stepsPerBar === 0) {         const marker = document.createElement("div");         marker.className = "step-marker";         marker.textContent = Math.floor(i / stepsPerBar) + 1;         stepWrapper.appendChild(marker);       }             stepWrapper.appendChild(stepElement);       sequencerContainer.appendChild(stepWrapper);     }   }); } export function updateGlobalPatternSelector() {     const globalPatternSelector = document.getElementById('global-pattern-selector');     if (!globalPatternSelector) return;     const referenceTrack = appState.pattern.tracks[0];     globalPatternSelector.innerHTML = '';     if (referenceTrack && referenceTrack.patterns.length > 0) {         referenceTrack.patterns.forEach((pattern, index) => {             const option = document.createElement('option');             option.value = index;             option.textContent = pattern.name;             globalPatternSelector.appendChild(option);         });         globalPatternSelector.selectedIndex = appState.pattern.activePatternIndex;         globalPatternSelector.disabled = false;     } else {         const option = document.createElement('option');         option.textContent = 'Sem patterns';         globalPatternSelector.appendChild(option);         globalPatternSelector.disabled = true;     } } export function highlightStep(stepIndex, isActive) {   if (stepIndex < 0) return;   document.querySelectorAll(".track-lane").forEach((track) => {     const stepWrapper = track.querySelector(       `.step-sequencer .step-wrapper:nth-child(${stepIndex + 1})`     );     if (stepWrapper) {       const stepElement = stepWrapper.querySelector(".step");       if (stepElement) {         stepElement.classList.toggle("playing", isActive);       }     }   }); } // (V7) Função de UI "cirúrgica" export function updateStepUI(trackIndex, patternIndex, stepIndex, isActive) { if (patternIndex !== appState.pattern.activePatternIndex) { return; } const trackElement = document.querySelector(`.track-lane[data-track-index="${trackIndex}"]`); if (!trackElement) return; const stepWrapper = trackElement.querySelector( `.step-sequencer .step-wrapper:nth-child(${stepIndex + 1})` ); if (!stepWrapper) return; const stepElement = stepWrapper.querySelector(".step"); if (!stepElement) return; stepElement.classList.toggle("active", isActive); }