perf: cut ControlApp re-renders and lazy-load VFX packs

Move audio scrub/volume and brush drafts off root React ticks, coalesce overlay layout IPC, cache machine fingerprint and asset URLs, share one scene overlay host, and stop idle Pixi ticker. Also harden console against EPIPE on window load failures.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Ivan Fontosh
2026-07-23 11:58:16 +08:00
parent 32a5479086
commit d9fbecf5a7
29 changed files with 1825 additions and 585 deletions
@@ -588,6 +588,7 @@ export const EDITOR_MESSAGES: Record<EditorLocale, Record<string, string>> = {
'control.transportPlay': 'Воспроизведение',
'control.transportPause': 'Пауза',
'control.transportStop': 'Стоп',
'control.volume': 'Громкость',
},
en: {
'common.close': 'Close',
@@ -1125,6 +1126,7 @@ export const EDITOR_MESSAGES: Record<EditorLocale, Record<string, string>> = {
'control.transportPlay': 'Play',
'control.transportPause': 'Pause',
'control.transportStop': 'Stop',
'control.volume': 'Volume',
},
};
@@ -19,6 +19,7 @@ import type {
SceneId,
} from '../../../shared/types';
import { getDndApi } from '../../shared/dndApi';
import { invalidateAssetUrlCache } from '../../shared/useAssetImageUrl';
type ProjectSummary = { id: ProjectId; name: string; updatedAt: string; fileName: string };
@@ -277,6 +278,8 @@ export function useProjectState(licenseActive: boolean, opts?: ProjectStateOpts)
projectDataEpochRef.current += 1;
const epoch = projectDataEpochRef.current;
openInFlightRef.current = null;
// URL ассетов зависят от открытого проекта — сбрасываем renderer-кэш.
invalidateAssetUrlCache();
const job = (async () => {
setState((s) => ({ ...s, openingProjectId: id }));
@@ -308,6 +311,7 @@ export function useProjectState(licenseActive: boolean, opts?: ProjectStateOpts)
const closeProject = async () => {
projectDataEpochRef.current += 1;
openInFlightRef.current = null;
invalidateAssetUrlCache();
try {
await api.invoke(ipcChannels.project.close, {});
} finally {