8f8eef53c9
- Optimize imported scene preview images (smart WebP/JPEG/PNG, preserve alpha, keep pixel size) - Update converter to re-encode existing image assets with same algorithm - Improve import/export progress overlay and reduce presentation slide stutter Made-with: Cursor
71 lines
2.4 KiB
TypeScript
71 lines
2.4 KiB
TypeScript
import type { Project } from '../../../shared/types';
|
|
import type { SceneId } from '../../../shared/types/ids';
|
|
|
|
import type { SceneGraphSceneAudioSummary, SceneGraphSceneCard } from './SceneGraph';
|
|
|
|
export function stableSceneGraphAudios(
|
|
prevCard: SceneGraphSceneCard | undefined,
|
|
nextRaw: SceneGraphSceneAudioSummary[],
|
|
): readonly SceneGraphSceneAudioSummary[] {
|
|
if (!prevCard) return nextRaw;
|
|
const pa = prevCard.audios;
|
|
if (pa.length !== nextRaw.length) return nextRaw;
|
|
for (let i = 0; i < nextRaw.length; i++) {
|
|
const p = pa[i];
|
|
const n = nextRaw[i];
|
|
if (p?.assetId !== n?.assetId || p?.loop !== n?.loop || p?.autoplay !== n?.autoplay) return nextRaw;
|
|
}
|
|
return pa;
|
|
}
|
|
|
|
export function buildNextSceneCardById(
|
|
prevRecord: Record<SceneId, SceneGraphSceneCard>,
|
|
project: Project,
|
|
): Record<SceneId, SceneGraphSceneCard> {
|
|
const nextMap: Record<SceneId, SceneGraphSceneCard> = {};
|
|
|
|
for (const id of Object.keys(project.scenes) as SceneId[]) {
|
|
const s = project.scenes[id];
|
|
if (!s) continue;
|
|
const prevCard = prevRecord[id];
|
|
const nextAudiosRaw: SceneGraphSceneAudioSummary[] = s.media.audios.map((a) => ({
|
|
assetId: a.assetId,
|
|
loop: a.loop,
|
|
autoplay: a.autoplay,
|
|
}));
|
|
const audios = stableSceneGraphAudios(prevCard, nextAudiosRaw);
|
|
const loopVideo = s.settings.loopVideo;
|
|
if (
|
|
prevCard?.title === s.title &&
|
|
prevCard.previewAssetId === s.previewAssetId &&
|
|
prevCard.previewThumbAssetId === s.previewThumbAssetId &&
|
|
prevCard.previewAssetType === s.previewAssetType &&
|
|
prevCard.previewVideoAutostart === s.previewVideoAutostart &&
|
|
prevCard.previewRotationDeg === s.previewRotationDeg &&
|
|
prevCard.loopVideo === loopVideo &&
|
|
prevCard.audios === audios
|
|
) {
|
|
nextMap[id] = prevCard;
|
|
} else {
|
|
nextMap[id] = {
|
|
title: s.title,
|
|
previewAssetId: s.previewAssetId,
|
|
previewThumbAssetId: s.previewThumbAssetId,
|
|
previewAssetType: s.previewAssetType,
|
|
previewVideoAutostart: s.previewVideoAutostart,
|
|
previewRotationDeg: s.previewRotationDeg,
|
|
loopVideo,
|
|
audios,
|
|
};
|
|
}
|
|
}
|
|
|
|
const prevKeys = Object.keys(prevRecord);
|
|
const nextKeys = Object.keys(nextMap);
|
|
const reuseRecord =
|
|
prevKeys.length === nextKeys.length &&
|
|
nextKeys.every((k) => prevRecord[k as SceneId] === nextMap[k as SceneId]);
|
|
|
|
return reuseRecord ? prevRecord : nextMap;
|
|
}
|