158 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
			
		
		
	
	
			158 lines
		
	
	
		
			5.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
// js/ui.js
 | 
						|
import { playSample } from "./pattern/pattern_audio.js";
 | 
						|
import { renderPatternEditor } from "./pattern/pattern_ui.js";
 | 
						|
import { renderAudioEditor } from "./audio/audio_ui.js";
 | 
						|
import { loadProjectFromServer } from "./file.js";
 | 
						|
 | 
						|
let samplePathMap = {};
 | 
						|
 | 
						|
export function renderAll() {
 | 
						|
    renderPatternEditor();
 | 
						|
    renderAudioEditor();
 | 
						|
    const loopArea = document.getElementById("loop-region"); 
 | 
						|
 | 
						|
    if (loopArea) {
 | 
						|
      // Sincroniza a visibilidade da área de loop com o estado atual
 | 
						|
      loopArea.classList.toggle("visible", appState.global.isLoopActive);
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
export function getSamplePathMap() {
 | 
						|
  return samplePathMap;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
//
 | 
						|
 | 
						|
function buildSamplePathMap(tree, currentPath) {
 | 
						|
  for (const key in tree) {
 | 
						|
    if (key === "_isFile") continue;
 | 
						|
    const node = tree[key];
 | 
						|
    const newPath = `${currentPath}/${key}`;
 | 
						|
    if (node._isFile) {
 | 
						|
      samplePathMap[key] = newPath;
 | 
						|
    } else {
 | 
						|
      buildSamplePathMap(node, newPath);
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
export async function loadAndRenderSampleBrowser() {
 | 
						|
  const browserContent = document.getElementById("browser-content");
 | 
						|
  try {
 | 
						|
    const response = await fetch(`metadata/samples-manifest.json?v=${Date.now()}`);
 | 
						|
    if (!response.ok) throw new Error("Arquivo samples-manifest.json não encontrado.");
 | 
						|
    const fileTree = await response.json();
 | 
						|
    
 | 
						|
    samplePathMap = {};
 | 
						|
    buildSamplePathMap(fileTree, "src/samples");
 | 
						|
    
 | 
						|
    renderFileTree(fileTree, browserContent, "src/samples");
 | 
						|
  } catch (error) {
 | 
						|
    console.error("Erro ao carregar samples:", error);
 | 
						|
    browserContent.innerHTML = `<p style="color:var(--accent-red); padding: 10px;">${error.message}</p>`;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
// Em ui.js, substitua a função antiga por esta:
 | 
						|
 | 
						|
function renderFileTree(tree, parentElement, currentPath) {
 | 
						|
    parentElement.innerHTML = ""; // Limpa o conteúdo anterior
 | 
						|
    const ul = document.createElement("ul");
 | 
						|
 | 
						|
    // Ordena para que as pastas sempre apareçam antes dos arquivos
 | 
						|
    const sortedKeys = Object.keys(tree).sort((a, b) => {
 | 
						|
      const aIsFile = tree[a]._isFile;
 | 
						|
      const bIsFile = tree[b]._isFile;
 | 
						|
      if (aIsFile === bIsFile) return a.localeCompare(b); // Ordena alfabeticamente se ambos forem do mesmo tipo
 | 
						|
      return aIsFile ? 1 : -1; // Pastas (-1) vêm antes de arquivos (1)
 | 
						|
    });
 | 
						|
 | 
						|
    for (const key of sortedKeys) {
 | 
						|
      if (key === '_isFile') continue; // Pula a propriedade de metadados
 | 
						|
 | 
						|
      const node = tree[key];
 | 
						|
      const li = document.createElement("li");
 | 
						|
      const newPath = `${currentPath}/${key}`;
 | 
						|
 | 
						|
      if (node._isFile) {
 | 
						|
        // --- LÓGICA PARA ARQUIVOS ---
 | 
						|
        li.className = "file-item draggable-sample"; // CORREÇÃO: Adiciona classe para consistência
 | 
						|
        li.innerHTML = `<i class="fa-solid fa-volume-high"></i> ${key}`; // Ícone mais apropriado
 | 
						|
        li.setAttribute("draggable", true);
 | 
						|
        li.dataset.path = newPath; // Guarda o caminho para o drag-and-drop
 | 
						|
 | 
						|
        li.addEventListener("click", (e) => {
 | 
						|
          e.stopPropagation();
 | 
						|
          playSample(newPath, null);
 | 
						|
        });
 | 
						|
 | 
						|
        li.addEventListener("dragstart", (e) => {
 | 
						|
          e.dataTransfer.setData("text/plain", newPath);
 | 
						|
          e.dataTransfer.effectAllowed = "copy";
 | 
						|
        });
 | 
						|
 | 
						|
        ul.appendChild(li);
 | 
						|
 | 
						|
      } else {
 | 
						|
        // --- LÓGICA CORRIGIDA PARA PASTAS ---
 | 
						|
        li.className = "folder-item"; // CORREÇÃO 1: Usa a classe CSS correta
 | 
						|
 | 
						|
        // CORREÇÃO 2: Cria o <span> clicável para o nome da pasta, que o CSS e o main.js esperam
 | 
						|
        const folderNameSpan = document.createElement("span");
 | 
						|
        folderNameSpan.className = "folder-name";
 | 
						|
        folderNameSpan.innerHTML = `<i class="folder-icon fa-solid fa-folder"></i> ${key}`;
 | 
						|
        li.appendChild(folderNameSpan);
 | 
						|
        
 | 
						|
        const nestedUl = document.createElement("ul");
 | 
						|
        nestedUl.className = "file-list"; // CORREÇÃO: Adiciona classe para o CSS
 | 
						|
        
 | 
						|
        // Chama a função recursivamente para os conteúdos da pasta
 | 
						|
        renderFileTree(node, nestedUl, newPath);
 | 
						|
        li.appendChild(nestedUl);
 | 
						|
 | 
						|
        // CORREÇÃO 3: Remove o addEventListener de clique daqui. O main.js já cuida disso.
 | 
						|
 | 
						|
        ul.appendChild(li);
 | 
						|
      }
 | 
						|
    }
 | 
						|
    parentElement.appendChild(ul);
 | 
						|
}
 | 
						|
 | 
						|
export async function showOpenProjectModal() {
 | 
						|
    const openProjectModal = document.getElementById("open-project-modal");
 | 
						|
    const serverProjectsList = document.getElementById("server-projects-list");
 | 
						|
    serverProjectsList.innerHTML = "<p>Carregando...</p>";
 | 
						|
    openProjectModal.classList.add("visible");
 | 
						|
    try {
 | 
						|
      const response = await fetch("metadata/mmp-manifest.json");
 | 
						|
      if (!response.ok) throw new Error("Arquivo mmp-manifest.json não encontrado.");
 | 
						|
      const projects = await response.json();
 | 
						|
  
 | 
						|
      serverProjectsList.innerHTML = "";
 | 
						|
      if (projects.length === 0) {
 | 
						|
        serverProjectsList.innerHTML = '<p style="color:var(--text-dark);">Nenhum projeto encontrado no servidor.</p>';
 | 
						|
      }
 | 
						|
  
 | 
						|
      projects.forEach((projectName) => {
 | 
						|
        const projectItem = document.createElement("div");
 | 
						|
        projectItem.className = "project-item";
 | 
						|
        projectItem.textContent = projectName;
 | 
						|
        projectItem.addEventListener("click", async () => {
 | 
						|
          const success = await loadProjectFromServer(projectName);
 | 
						|
          if (success) {
 | 
						|
            closeOpenProjectModal();
 | 
						|
          }
 | 
						|
        });
 | 
						|
        serverProjectsList.appendChild(projectItem);
 | 
						|
      });
 | 
						|
    } catch (error) {
 | 
						|
      console.error("Erro ao carregar lista de projetos:", error);
 | 
						|
      serverProjectsList.innerHTML = `<p style="color:var(--accent-red);">${error.message}</p>`;
 | 
						|
    }
 | 
						|
}
 | 
						|
  
 | 
						|
export function closeOpenProjectModal() {
 | 
						|
    const openProjectModal = document.getElementById("open-project-modal");
 | 
						|
    openProjectModal.classList.remove("visible");
 | 
						|
} |