fix: game audio persistence and editor perf

- Keep game/campaign audio assets referenced (no prune)
- Flush pending project save on quit/switch/export to avoid losing campaignAudios
- Control: prevent game music restarts on scene changes; allow always-on controls; handle autoplay-after-scene-audio
- Editor: reduce ReactFlow churn with stable scene card map; lazy/async image decode
- Add contract/unit tests and update test script

Made-with: Cursor
This commit is contained in:
Ivan Fontosh
2026-04-22 19:06:16 +08:00
parent f823a7c05f
commit 1d051f8bf9
19 changed files with 1164 additions and 115 deletions
+20
View File
@@ -19,6 +19,8 @@ type Actions = {
closeProject: () => Promise<void>;
createScene: () => Promise<void>;
selectScene: (id: SceneId) => Promise<void>;
importCampaignAudio: () => Promise<void>;
updateCampaignAudios: (next: Project['campaignAudios']) => Promise<void>;
updateScene: (
sceneId: SceneId,
patch: {
@@ -129,6 +131,22 @@ export function useProjectState(licenseActive: boolean): readonly [State, Action
await api.invoke(ipcChannels.project.setCurrentScene, { sceneId: id });
};
const importCampaignAudio = async () => {
const res = await api.invoke(ipcChannels.project.importCampaignAudio, {});
if (res.canceled) return;
if (res.imported.length === 0) {
window.alert('Аудио не добавлено. Проверьте формат файла.');
}
setState((s) => ({ ...s, project: res.project }));
await refreshProjects();
};
const updateCampaignAudios = async (next: Project['campaignAudios']) => {
const res = await api.invoke(ipcChannels.project.updateCampaignAudios, { audios: next });
setState((s) => ({ ...s, project: res.project }));
await refreshProjects();
};
const updateScene = async (
sceneId: SceneId,
patch: {
@@ -299,6 +317,8 @@ export function useProjectState(licenseActive: boolean): readonly [State, Action
closeProject,
createScene,
selectScene,
importCampaignAudio,
updateCampaignAudios,
updateScene,
updateConnections,
importMediaToScene,