plugin v1.0.1
Deploy / Deploy (push) Successful in 1m21s Details

This commit is contained in:
JotaChina 2025-11-23 17:48:27 -03:00
parent ebaa0f81bf
commit c332ce07cd
3 changed files with 71 additions and 46 deletions

View File

@ -314,11 +314,11 @@ export async function parseMmpContent(xmlString) {
console.log("Restaurando estado temporário da sessão..."); console.log("Restaurando estado temporário da sessão...");
const tempState = JSON.parse(tempStateJSON); const tempState = JSON.parse(tempStateJSON);
// 1. Restaura Pattern (código que já existia)
appState.pattern.tracks.forEach((liveTrack) => { appState.pattern.tracks.forEach((liveTrack) => {
const savedTrack = tempState.pattern.tracks.find( const savedTrack = tempState.pattern.tracks.find(
(t) => t.id === liveTrack.id (t) => t.id === liveTrack.id
); );
if (savedTrack) { if (savedTrack) {
liveTrack.name = savedTrack.name; liveTrack.name = savedTrack.name;
liveTrack.patterns = savedTrack.patterns; liveTrack.patterns = savedTrack.patterns;
@ -335,14 +335,33 @@ export async function parseMmpContent(xmlString) {
} }
}); });
// Filtra tracks deletadas
appState.pattern.tracks = appState.pattern.tracks.filter((liveTrack) => appState.pattern.tracks = appState.pattern.tracks.filter((liveTrack) =>
tempState.pattern.tracks.some((t) => t.id === liveTrack.id) tempState.pattern.tracks.some((t) => t.id === liveTrack.id)
); );
// 2. 🔥 FIX: Restaura Áudio (Clips e Tracks)
if (tempState.audio) {
console.log("Restaurando faixas de áudio e clips...");
appState.audio.tracks = tempState.audio.tracks || [];
appState.audio.clips = tempState.audio.clips || [];
}
// 3. Restaura Global
document.getElementById("bpm-input").value = tempState.global.bpm; document.getElementById("bpm-input").value = tempState.global.bpm;
document.getElementById("compasso-a-input").value = tempState.global.compassoA; document.getElementById("compasso-a-input").value = tempState.global.compassoA;
document.getElementById("compasso-b-input").value = tempState.global.compassoB; document.getElementById("compasso-b-input").value = tempState.global.compassoB;
document.getElementById("bars-input").value = tempState.global.bars; document.getElementById("bars-input").value = tempState.global.bars;
if (tempState.global.syncMode) {
appState.global.syncMode = tempState.global.syncMode;
// Atualiza visual do botão sync se existir (pode precisar disparar evento ou fazer manual)
const syncBtn = document.getElementById("sync-mode-btn");
if (syncBtn) {
syncBtn.classList.toggle("active", tempState.global.syncMode === "global");
syncBtn.textContent = tempState.global.syncMode === "global" ? "Global" : "Local";
}
}
appState.pattern.activeTrackId = tempState.pattern.activeTrackId; appState.pattern.activeTrackId = tempState.pattern.activeTrackId;
} }

View File

@ -198,35 +198,36 @@ socket.on("load_project_state", async (projectXml) => {
showToast("🎵 Projeto carregado com sucesso", "success"); showToast("🎵 Projeto carregado com sucesso", "success");
// --- INÍCIO DA CORREÇÃO --- // --- INÍCIO DA CORREÇÃO ---
// Mova a lógica de snapshot para AQUI.
// Só peça um snapshot DEPOIS que o XML foi carregado
// e SE o XML (appState) não tiver áudio.
const hasAudio = const hasAudio =
(appState.audio?.clips?.length || 0) > 0 || (appState.audio?.clips?.length || 0) > 0 ||
(appState.audio?.tracks?.length || 0) > 0; (appState.audio?.tracks?.length || 0) > 0;
if (!hasAudio && currentRoom) { if (!hasAudio && currentRoom) {
console.log( console.log(
"Projeto XML carregado, sem áudio. Pedindo snapshot de áudio..." "Projeto XML carregado, sem áudio. Pedindo snapshot de áudio..."
); );
// O 'sendAction' agora é chamado daqui, não do joinRoom.
// 🔥 FIX CRÍTICO: Libera a trava IMEDIATAMENTE antes de pedir
// Caso contrário, a resposta chega muito rápido e cai no bloqueio "justReset=true"
appState.global.justReset = false;
sendAction({ type: "AUDIO_SNAPSHOT_REQUEST" }); sendAction({ type: "AUDIO_SNAPSHOT_REQUEST" });
} }
// --- FIM DA CORREÇÃO --- // --- FIM DA CORREÇÃO ---
} catch (e) { } catch (e) {
console.error("Erro ao carregar projeto:", e); console.error("Erro ao carregar projeto:", e);
showToast("❌ Erro ao carregar projeto", "error"); showToast("❌ Erro ao carregar projeto", "error");
} }
isLoadingProject = false; isLoadingProject = false;
// Desativa a flag de reset após um delay.
// Isso dá tempo para a "condição de corrida" (o snapshot sujo) // Mantemos o timeout apenas como segurança extra para outros casos
// ser recebida e ignorada.
setTimeout(() => { setTimeout(() => {
if (appState.global.justReset) { if (appState.global.justReset) {
console.log("Socket: Limpando flag 'justReset'."); // console.log("Socket: Limpando flag 'justReset' (timeout).");
appState.global.justReset = false; appState.global.justReset = false;
} }
}, 250); // 2.5 segundos de "janela de proteção" }, 250);
// --- FIM DA CORREÇÃO ---
}); });
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------

View File

@ -100,49 +100,54 @@ export function resetProjectState() {
import { generateXmlFromStateExported } from "./file.js"; // Vamos assumir que você vai exportar isso no file.js import { generateXmlFromStateExported } from "./file.js"; // Vamos assumir que você vai exportar isso no file.js
export function saveStateToSession() { export function saveStateToSession() {
// Só salva se estiver em uma sala (contexto colaborativo/online)
if (!window.ROOM_NAME) return; if (!window.ROOM_NAME) return;
try { // 1. Crie uma versão "limpa" dos tracks (PATTERN)
// 1. Snapshot do Áudio (inclui blobs Base64 das gravações) const cleanTracks = appState.pattern.tracks.map((track) => {
const audioSnap = getAudioSnapshot(); return {
id: track.id,
// 2. Snapshot do Pattern (XML) name: track.name,
// Se não conseguirmos o XML exato, salvamos os dados brutos do pattern samplePath: track.samplePath,
let xmlContent = null; patterns: track.patterns,
try { activePatternIndex: track.activePatternIndex,
// Tenta usar a função exportada (veja nota abaixo sobre file.js) volume: track.volume,
if(typeof generateXmlFromStateExported === 'function') { pan: track.pan,
xmlContent = generateXmlFromStateExported(); instrumentName: track.instrumentName,
} instrumentXml: track.instrumentXml,
} catch(e) {
console.warn("Não foi possível gerar XML para backup:", e);
}
const stateToSave = {
timestamp: Date.now(),
xml: xmlContent,
// Fallback: Salva o pattern bruto se o XML falhar
patternRaw: !xmlContent ? appState.pattern : null,
audio: audioSnap,
global: {
bpm: appState.global.bpm, // Pega do state, que deve estar syncado com o DOM
compassoA: appState.global.compassoA,
compassoB: appState.global.compassoB,
bars: appState.global.bars,
syncMode: appState.global.syncMode
}
}; };
});
const roomName = window.ROOM_NAME; // 2. Construa o objeto de estado final para salvar
sessionStorage.setItem(`mmp_backup_${roomName}`, JSON.stringify(stateToSave)); const stateToSave = {
// console.log("Estado salvo na sessão local (F5 safe)."); pattern: {
...appState.pattern,
tracks: cleanTracks,
},
// 🔥 FIX: Salvando o estado de Áudio (Tracks e Clips)
audio: {
tracks: appState.audio.tracks || [],
clips: appState.audio.clips || [],
// Adicione outras props de áudio se necessário (ex: seekTime, etc)
},
global: {
bpm: document.getElementById("bpm-input").value,
compassoA: document.getElementById("compasso-a-input").value,
compassoB: document.getElementById("compasso-b-input").value,
bars: document.getElementById("bars-input").value,
syncMode: appState.global.syncMode, // É bom salvar isso também
},
};
try {
const roomName = window.ROOM_NAME || "default_room";
sessionStorage.setItem(
`temp_state_${roomName}`,
JSON.stringify(stateToSave)
);
} catch (e) { } catch (e) {
console.error("Falha crítica ao salvar sessão (Quota Excedida?):", e); console.error("Falha ao salvar estado na sessão:", e);
} }
} }
export async function loadStateFromSession() { export async function loadStateFromSession() {
const roomName = window.ROOM_NAME; const roomName = window.ROOM_NAME;
if (!roomName) return false; if (!roomName) return false;