mmpSearch/assets/js/creations/state.js

211 lines
6.1 KiB
JavaScript

// 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;
}
}