// js/state.js import { initializePatternState } from "./pattern/pattern_state.js"; import { audioState, initializeAudioState } from "./audio/audio_state.js"; import { DEFAULT_VOLUME, DEFAULT_PAN } from "./config.js"; import * as Tone from "https://esm.sh/tone"; // Adicione esta importação // Estado global da aplicação const globalState = { sliceToolActive: false, isPlaying: false, isAudioEditorPlaying: false, playbackIntervalId: null, currentStep: 0, metronomeEnabled: false, originalXmlDoc: null, currentBeatBasslineName: "Novo Projeto", masterVolume: DEFAULT_VOLUME, masterPan: DEFAULT_PAN, zoomLevelIndex: 2, isLoopActive: false, loopStartTime: 0, loopEndTime: 8, resizeMode: "trim", selectedClipId: null, isRecording: false, clipboard: null, lastRulerClickTime: 0, justReset: false, }; // Define o ESTADO INICIAL para o pattern module const patternState = { tracks: [], activeTrackId: null, activePatternIndex: 0, }; // Combina todos os estados em um único objeto namespaced export let appState = { global: globalState, pattern: patternState, audio: audioState, }; window.appState = appState; export function resetProjectState() { console.log("Executando resetProjectState completo..."); // 1. Reseta o estado global Object.assign(appState.global, { sliceToolActive: false, isPlaying: false, isAudioEditorPlaying: false, playbackIntervalId: null, currentStep: 0, metronomeEnabled: false, originalXmlDoc: null, currentBeatBasslineName: "Novo Projeto", masterVolume: DEFAULT_VOLUME, masterPan: DEFAULT_PAN, zoomLevelIndex: 2, isLoopActive: false, loopStartTime: 0, loopEndTime: 8, resizeMode: "trim", selectedClipId: null, isRecording: false, clipboard: null, lastRulerClickTime: 0, justReset: false, }); // 2. Reseta o estado do pattern Object.assign(appState.pattern, { tracks: [], activeTrackId: null, activePatternIndex: 0, }); // 3. Reseta o estado de áudio (Força bruta para garantir limpeza na memória) if (appState.audio) { appState.audio.tracks = []; appState.audio.clips = []; appState.audio.audioEditorSeekTime = 0; } initializeAudioState(); } export function saveStateToSession() { if (!window.ROOM_NAME) return; // 1. Crie uma versão "limpa" dos tracks const cleanTracks = appState.pattern.tracks.map((track) => { return { id: track.id, name: track.name, samplePath: track.samplePath, patterns: track.patterns, activePatternIndex: track.activePatternIndex, volume: track.volume, pan: track.pan, instrumentName: track.instrumentName, instrumentXml: track.instrumentXml, }; }); // 2. Construa o objeto de estado final para salvar const stateToSave = { pattern: { ...appState.pattern, tracks: cleanTracks, }, audio: { tracks: appState.audio.tracks || [], clips: appState.audio.clips || [], }, global: { bpm: document.getElementById("bpm-input")?.value || 140, compassoA: document.getElementById("compasso-a-input")?.value || 4, compassoB: document.getElementById("compasso-b-input")?.value || 4, bars: document.getElementById("bars-input")?.value || 1, syncMode: appState.global.syncMode, }, }; try { const roomName = window.ROOM_NAME || "default_room"; sessionStorage.setItem( `temp_state_${roomName}`, JSON.stringify(stateToSave) ); } catch (e) { console.error("Falha ao salvar estado na sessão:", e); } } // --- NOVA FUNÇÃO PARA CORRIGIR O ERRO --- export function loadStateFromSession() { const roomName = window.ROOM_NAME || "default_room"; const tempStateJSON = sessionStorage.getItem(`temp_state_${roomName}`); if (!tempStateJSON) return false; console.log("Restaurando estado da sessão..."); try { const tempState = JSON.parse(tempStateJSON); // 1. Restaura Pattern Tracks appState.pattern.tracks.forEach((liveTrack) => { const savedTrack = tempState.pattern.tracks.find( (t) => t.id === liveTrack.id ); if (savedTrack) { liveTrack.name = savedTrack.name; liveTrack.patterns = savedTrack.patterns; liveTrack.activePatternIndex = savedTrack.activePatternIndex; liveTrack.volume = savedTrack.volume; liveTrack.pan = savedTrack.pan; if (liveTrack.volumeNode) { liveTrack.volumeNode.volume.value = Tone.gainToDb(savedTrack.volume); } if (liveTrack.pannerNode) { liveTrack.pannerNode.pan.value = savedTrack.pan; } } }); // Filtra tracks que não existem mais no salvo appState.pattern.tracks = appState.pattern.tracks.filter((liveTrack) => tempState.pattern.tracks.some((t) => t.id === liveTrack.id) ); // 2. Restaura Áudio if (tempState.audio) { appState.audio.tracks = tempState.audio.tracks || []; appState.audio.clips = tempState.audio.clips || []; } // 3. Restaura Global if (tempState.global) { const bpmInput = document.getElementById("bpm-input"); if (bpmInput) bpmInput.value = tempState.global.bpm; const compassoA = document.getElementById("compasso-a-input"); if (compassoA) compassoA.value = tempState.global.compassoA; const compassoB = document.getElementById("compasso-b-input"); if (compassoB) compassoB.value = tempState.global.compassoB; const barsInput = document.getElementById("bars-input"); if (barsInput) barsInput.value = tempState.global.bars; if (tempState.global.syncMode) { appState.global.syncMode = tempState.global.syncMode; 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; return true; } catch (e) { console.error("Erro ao carregar estado da sessão:", e); return false; } }