feat(scenes): add scene darkness reveal and fix project reopen crash

Add darkenScene with Opening brush in presentation, persist reveal strokes per scene during a session, and close projects properly on return to home. Harden dnd asset streaming to avoid Windows main-process crashes when reopening projects.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Ivan Fontosh
2026-07-02 19:41:26 +08:00
parent d54e9ed02d
commit 4631a1bece
19 changed files with 526 additions and 11 deletions
+21
View File
@@ -623,6 +623,7 @@ export function EditorApp() {
previewAssetType={sc?.previewAssetType ?? null}
previewVideoAutostart={sc?.previewVideoAutostart ?? false}
previewRotationDeg={sc?.previewRotationDeg ?? 0}
darkenScene={sc?.darkenScene ?? false}
previewBusy={previewBusy}
mediaAssets={sceneMediaAssets}
audioRefs={sceneAudioRefs}
@@ -632,6 +633,9 @@ export function EditorApp() {
onPreviewVideoAutostartChange={(next) =>
void actions.updateScene(sid, { previewVideoAutostart: next })
}
onDarkenSceneChange={(next) =>
void actions.updateScene(sid, { darkenScene: next })
}
onTitleChange={(title) => void actions.updateScene(sid, { title })}
onDescriptionChange={(description) =>
void actions.updateScene(sid, { description })
@@ -1681,11 +1685,13 @@ type SceneInspectorProps = {
previewAssetType: 'image' | 'video' | null;
previewVideoAutostart: boolean;
previewRotationDeg: 0 | 90 | 180 | 270;
darkenScene: boolean;
previewBusy: boolean;
mediaAssets: MediaAsset[];
audioRefs: SceneAudioRef[];
onAudioRefsChange: (next: SceneAudioRef[]) => void;
onPreviewVideoAutostartChange: (next: boolean) => void;
onDarkenSceneChange: (next: boolean) => void;
onTitleChange: (v: string) => void;
onDescriptionChange: (v: string) => void;
onImportPreview: () => void;
@@ -1788,11 +1794,13 @@ function SceneInspector({
previewAssetType,
previewVideoAutostart,
previewRotationDeg,
darkenScene,
previewBusy,
mediaAssets,
audioRefs,
onAudioRefsChange,
onPreviewVideoAutostartChange,
onDarkenSceneChange,
onTitleChange,
onDescriptionChange,
onImportPreview,
@@ -1877,6 +1885,19 @@ function SceneInspector({
</Button>
) : null}
</div>
{previewAssetId && previewAssetType === 'image' ? (
<>
<div className={styles.spacer6} />
<label className={styles.checkboxLabel}>
<input
type="checkbox"
checked={darkenScene}
onChange={(e) => onDarkenSceneChange(e.target.checked)}
/>
<span className={styles.spanSm}>{t('scene.darkenScene')}</span>
</label>
</>
) : null}
<div className={styles.spacer6} />
<div className={styles.labelSm}>{t('scene.audio')}</div>
<div className={styles.audioDrop}>