mmpSearch/assets/js/creations/ui.js

156 lines
5.7 KiB
JavaScript

// js/ui.js
import { appState } from "./state.js"; // <-- CORREÇÃO: Importação adicionada
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");
}