@hyperframes/studio 0.8.35 → 0.8.36

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/dist/assets/{hyperframes-player-lPOqAC3l.js → hyperframes-player-BIpJmC69.js} +1 -1
  2. package/dist/assets/index-BmPeyP0k.js +441 -0
  3. package/dist/assets/{index-ywAULfGT.js → index-Df3VgdgL.js} +1 -1
  4. package/dist/assets/{index-RPEcu_bT.js → index-z2_QKypm.js} +1 -1
  5. package/dist/index.html +1 -1
  6. package/dist/index.js +61 -195
  7. package/dist/index.js.map +1 -1
  8. package/package.json +7 -7
  9. package/src/App.tsx +0 -7
  10. package/src/components/StudioRightPanel.tsx +0 -7
  11. package/src/components/StudioRightPanel.types.ts +0 -2
  12. package/src/components/editor/SnapToolbar.test.tsx +0 -2
  13. package/src/components/editor/manualEdits.test.ts +3 -3
  14. package/src/components/editor/manualEdits.ts +1 -1
  15. package/src/components/editor/manualEditsParsing.ts +12 -21
  16. package/src/components/panels/VariablesOtherCompositions.tsx +1 -4
  17. package/src/components/panels/VariablesPanel.tsx +1 -5
  18. package/src/components/studioColorGradingScope.ts +0 -4
  19. package/src/hooks/elementLifecycleOpsTestUtils.ts +0 -1
  20. package/src/hooks/externalFileChangeOwnership.test.ts +40 -1
  21. package/src/hooks/gsapScriptCommitTypes.ts +0 -1
  22. package/src/hooks/sdkSelfWriteRegistry.ts +1 -1
  23. package/src/hooks/timelineAudioGroupCreate.ts +0 -7
  24. package/src/hooks/timelineAudioGroupVolume.test.ts +0 -1
  25. package/src/hooks/timelineAudioGroupVolume.ts +0 -6
  26. package/src/hooks/timelineEditingHelpers.test.ts +0 -3
  27. package/src/hooks/timelineEditingHelpers.ts +0 -10
  28. package/src/hooks/timelineElementFxAttribute.ts +0 -6
  29. package/src/hooks/timelineTrackVisibility.test.ts +0 -17
  30. package/src/hooks/timelineTrackVisibility.ts +0 -15
  31. package/src/hooks/useAppHotkeys.previewForwarding.test.tsx +0 -1
  32. package/src/hooks/useAppHotkeys.textEditing.test.tsx +0 -2
  33. package/src/hooks/useAppHotkeys.ts +1 -7
  34. package/src/hooks/useAudioGroupCarveAssignment.test.tsx +0 -1
  35. package/src/hooks/useClipboard.ts +1 -11
  36. package/src/hooks/useDomEditCommits.test.tsx +0 -2
  37. package/src/hooks/useDomEditCommits.ts +2 -21
  38. package/src/hooks/useDomEditSession.test.tsx +0 -1
  39. package/src/hooks/useDomEditSession.ts +0 -7
  40. package/src/hooks/useEditorSave.test.tsx +0 -1
  41. package/src/hooks/useEditorSave.ts +2 -6
  42. package/src/hooks/useElementLifecycleOps.ts +0 -3
  43. package/src/hooks/useExternalFileChangeCoordinator.test.tsx +54 -0
  44. package/src/hooks/useExternalFileChangeCoordinator.ts +38 -22
  45. package/src/hooks/useFileManager.projectOwnership.test.tsx +0 -1
  46. package/src/hooks/useFileManager.ts +0 -3
  47. package/src/hooks/useGroupCommits.ts +0 -2
  48. package/src/hooks/useGsapScriptCommits.test.tsx +0 -2
  49. package/src/hooks/useGsapScriptCommits.ts +2 -5
  50. package/src/hooks/usePreviewInteraction.test.ts +14 -5
  51. package/src/hooks/usePreviewInteraction.ts +3 -3
  52. package/src/hooks/useProjectCompositionVariables.ts +3 -6
  53. package/src/hooks/useRazorSplit.history.test.tsx +0 -2
  54. package/src/hooks/useRazorSplit.test.ts +0 -2
  55. package/src/hooks/useRazorSplit.test.tsx +0 -1
  56. package/src/hooks/useRazorSplit.ts +0 -6
  57. package/src/hooks/useSdkSession.ts +3 -11
  58. package/src/hooks/useSlideshowPersist.ts +1 -5
  59. package/src/hooks/useTimelineAssetDropOps.ts +0 -6
  60. package/src/hooks/useTimelineDeleteOps.ts +0 -4
  61. package/src/hooks/useTimelineEditing.test.tsx +0 -3
  62. package/src/hooks/useTimelineEditing.ts +0 -16
  63. package/src/hooks/useTimelineEditingTypes.ts +0 -1
  64. package/src/hooks/useTimelineGroupEditing.ts +0 -6
  65. package/src/hooks/useVariablesPersist.ts +0 -3
  66. package/src/player/components/Player.tsx +18 -5
  67. package/src/player/components/playerModuleRetry.test.ts +41 -0
  68. package/src/player/lib/playbackTypes.ts +7 -0
  69. package/src/player/lib/timelineIframeHelpers.test.ts +30 -0
  70. package/src/player/lib/timelineIframeHelpers.ts +16 -0
  71. package/src/utils/sdkCutover.familyGate.test.ts +0 -1
  72. package/src/utils/sdkCutover.gate.test.ts +0 -1
  73. package/src/utils/sdkCutover.test.ts +0 -27
  74. package/src/utils/sdkEditTransaction.ts +0 -4
  75. package/src/utils/setSlideshowManifest.test.ts +0 -1
  76. package/src/utils/studioFileHistory.ts +0 -1
  77. package/dist/assets/index-BRr1JoHX.js +0 -441
  78. package/src/hooks/useSdkSession.test.ts +0 -32
package/dist/index.js CHANGED
@@ -446,6 +446,16 @@ function Tooltip({ label, children, delay: delay2 = 400, side = "top" }) {
446
446
 
447
447
  // src/player/components/Player.tsx
448
448
  import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
449
+ var playerModule = null;
450
+ function loadPlayerModule() {
451
+ playerModule ??= import("@hyperframes/player").catch((err) => {
452
+ playerModule = null;
453
+ throw err;
454
+ });
455
+ return playerModule;
456
+ }
457
+ if (typeof window !== "undefined") void loadPlayerModule().catch(() => {
458
+ });
449
459
  var MEDIA_HAVE_FUTURE_DATA = 3;
450
460
  var MEDIA_NETWORK_NO_SOURCE = 3;
451
461
  function isRecord(value) {
@@ -543,7 +553,7 @@ var Player = forwardRef2(
543
553
  if (!previewSource) return;
544
554
  let canceled = false;
545
555
  let cleanup;
546
- import("@hyperframes/player").then(() => {
556
+ void loadPlayerModule().then(() => {
547
557
  if (canceled) return;
548
558
  const player = document.createElement("hyperframes-player");
549
559
  const srcUrl = new URL(previewSource, window.location.origin);
@@ -3780,11 +3790,18 @@ function resolveScrubAudioEl(doc, musicId) {
3780
3790
  }
3781
3791
  return doc.querySelector("audio[data-timeline-role='music']") ?? doc.querySelector("audio");
3782
3792
  }
3793
+ function leaseScrubElement(el) {
3794
+ el.ownerDocument.defaultView?.__hf?.leasePausedMedia?.(el);
3795
+ }
3796
+ function releaseScrubElement(el) {
3797
+ el.ownerDocument.defaultView?.__hf?.releasePausedMedia?.(el);
3798
+ }
3783
3799
  function applyScrub(el, audioFileTime, previewVolume) {
3784
3800
  if (scrubAudioEl && scrubAudioEl !== el) stopScrubPreviewAudio();
3785
3801
  if (scrubPrevMuted === null) scrubPrevMuted = el.muted;
3786
3802
  if (scrubPrevVolume === null) scrubPrevVolume = el.volume;
3787
3803
  scrubAudioEl = el;
3804
+ leaseScrubElement(el);
3788
3805
  try {
3789
3806
  el.muted = false;
3790
3807
  el.volume = SCRUB_VOLUME * normalizePreviewVolume(previewVolume);
@@ -3820,6 +3837,7 @@ function stopScrubPreviewAudio() {
3820
3837
  const el = scrubAudioEl;
3821
3838
  scrubAudioEl = null;
3822
3839
  if (!el) return;
3840
+ releaseScrubElement(el);
3823
3841
  try {
3824
3842
  el.pause();
3825
3843
  if (scrubPrevMuted !== null) el.muted = scrubPrevMuted;
@@ -17303,7 +17321,6 @@ async function persistTimelineEdit(input) {
17303
17321
  throw new Error(`Unable to patch timeline element ${input.element.id} in ${targetPath}`);
17304
17322
  }
17305
17323
  input.pendingTimelineEditPathRef.current.add(targetPath);
17306
- input.domEditSaveTimestampRef.current = Date.now();
17307
17324
  await saveProjectFilesWithHistory({
17308
17325
  projectId: input.projectId,
17309
17326
  label: input.label,
@@ -17314,7 +17331,6 @@ async function persistTimelineEdit(input) {
17314
17331
  writeFile: input.writeProjectFile,
17315
17332
  recordEdit: input.recordEdit
17316
17333
  });
17317
- input.domEditSaveTimestampRef.current = Date.now();
17318
17334
  }
17319
17335
  async function persistTimelineBatchEdit(input) {
17320
17336
  const originals = /* @__PURE__ */ new Map();
@@ -17340,7 +17356,6 @@ async function persistTimelineBatchEdit(input) {
17340
17356
  for (const targetPath of Object.keys(files)) {
17341
17357
  input.pendingTimelineEditPathRef.current.add(targetPath);
17342
17358
  }
17343
- input.domEditSaveTimestampRef.current = Date.now();
17344
17359
  await saveProjectFilesWithHistory({
17345
17360
  projectId: input.projectId,
17346
17361
  label: input.label,
@@ -17352,7 +17367,6 @@ async function persistTimelineBatchEdit(input) {
17352
17367
  writeFile: input.writeProjectFile,
17353
17368
  recordEdit: input.recordEdit
17354
17369
  });
17355
- input.domEditSaveTimestampRef.current = Date.now();
17356
17370
  }
17357
17371
  async function persistElementAttribute({
17358
17372
  projectId,
@@ -17363,7 +17377,6 @@ async function persistElementAttribute({
17363
17377
  label,
17364
17378
  writeProjectFile,
17365
17379
  recordEdit,
17366
- domEditSaveTimestampRef,
17367
17380
  pendingTimelineEditPathRef,
17368
17381
  patchLive
17369
17382
  }) {
@@ -17376,7 +17389,6 @@ async function persistElementAttribute({
17376
17389
  const operation = { type: "attribute", property: attr, value };
17377
17390
  const patched = applyPatchByTarget(before, patchTarget, operation);
17378
17391
  pendingTimelineEditPathRef.current.add(targetPath);
17379
- domEditSaveTimestampRef.current = Date.now();
17380
17392
  try {
17381
17393
  const changedPaths = await saveProjectFilesWithHistory({
17382
17394
  projectId,
@@ -17387,7 +17399,6 @@ async function persistElementAttribute({
17387
17399
  writeFile: writeProjectFile,
17388
17400
  recordEdit
17389
17401
  });
17390
- domEditSaveTimestampRef.current = Date.now();
17391
17402
  return changedPaths;
17392
17403
  } catch (error) {
17393
17404
  patchLive(previousValue);
@@ -29983,28 +29994,15 @@ function roundRotationAngle(angle) {
29983
29994
  function normalizeStudioFileChangePath(path) {
29984
29995
  return path.trim().replace(/\\/g, "/").replace(/^\.?\//, "");
29985
29996
  }
29986
- function readStudioFileChangePathFromValue(value) {
29987
- if (typeof value === "string") {
29988
- const trimmed = value.trim();
29989
- if (!trimmed) return null;
29990
- if (trimmed.startsWith("{")) {
29991
- try {
29992
- return readStudioFileChangePathFromValue(JSON.parse(trimmed));
29993
- } catch {
29994
- return normalizeStudioFileChangePath(trimmed);
29995
- }
29996
- }
29997
- return normalizeStudioFileChangePath(trimmed);
29998
- }
29999
- if (!value || typeof value !== "object") return null;
30000
- const record = value;
30001
- if (typeof record.path === "string") return normalizeStudioFileChangePath(record.path);
30002
- if (typeof record.filePath === "string") return normalizeStudioFileChangePath(record.filePath);
30003
- if ("data" in record) return readStudioFileChangePathFromValue(record.data);
30004
- return null;
29997
+ function readFileChangeField(payload, key2) {
29998
+ if (!payload || typeof payload !== "object") return null;
29999
+ const record = payload;
30000
+ const value = record[key2];
30001
+ return typeof value === "string" ? value : null;
30005
30002
  }
30006
30003
  function readStudioFileChangePath(payload) {
30007
- return readStudioFileChangePathFromValue(payload);
30004
+ const path = readFileChangeField(payload, "path") ?? readFileChangeField(payload, "filePath");
30005
+ return path === null ? null : normalizeStudioFileChangePath(path);
30008
30006
  }
30009
30007
 
30010
30008
  // src/components/editor/gsapAnimatesProperty.ts
@@ -38851,7 +38849,6 @@ function isCutoverResult(value) {
38851
38849
  }
38852
38850
  async function rollbackWrite(targetPath, originalContent, expectedCurrentContent, deps, cause) {
38853
38851
  try {
38854
- deps.domEditSaveTimestampRef.current = Date.now();
38855
38852
  markSelfWrite(targetPath, originalContent);
38856
38853
  await deps.writeProjectFile(targetPath, originalContent, expectedCurrentContent);
38857
38854
  return cause;
@@ -38863,7 +38860,6 @@ async function rollbackWrite(targetPath, originalContent, expectedCurrentContent
38863
38860
  }
38864
38861
  }
38865
38862
  async function writeAndRecord(after, targetPath, originalContent, deps, options) {
38866
- deps.domEditSaveTimestampRef.current = Date.now();
38867
38863
  markSelfWrite(targetPath, after);
38868
38864
  try {
38869
38865
  await deps.writeProjectFile(targetPath, after, originalContent);
@@ -39301,7 +39297,6 @@ function useElementLifecycleOps({
39301
39297
  activeCompPath,
39302
39298
  showToast,
39303
39299
  writeProjectFile,
39304
- domEditSaveTimestampRef,
39305
39300
  editHistory,
39306
39301
  projectIdRef,
39307
39302
  reloadPreview,
@@ -39351,7 +39346,6 @@ function useElementLifecycleOps({
39351
39346
  return { ok: true };
39352
39347
  }
39353
39348
  }
39354
- domEditSaveTimestampRef.current = Date.now();
39355
39349
  const removeResponse = await fetch(
39356
39350
  buildProjectApiPath(
39357
39351
  pid,
@@ -39407,7 +39401,6 @@ function useElementLifecycleOps({
39407
39401
  [
39408
39402
  activeCompPath,
39409
39403
  clearDomSelection,
39410
- domEditSaveTimestampRef,
39411
39404
  editHistory.recordEdit,
39412
39405
  onTrySdkDelete,
39413
39406
  onElementDeleted,
@@ -65226,7 +65219,6 @@ function useEditorSave({
65226
65219
  readProjectFile,
65227
65220
  writeProjectFile,
65228
65221
  recordEdit,
65229
- domEditSaveTimestampRef,
65230
65222
  setRefreshKey,
65231
65223
  showToast
65232
65224
  }) {
@@ -65310,11 +65302,10 @@ function useEditorSave({
65310
65302
  if (saveRafRef.current != null) cancelAnimationFrame(saveRafRef.current);
65311
65303
  saveRafRef.current = requestAnimationFrame(() => {
65312
65304
  saveRafRef.current = null;
65313
- domEditSaveTimestampRef.current = Date.now();
65314
65305
  void persistCandidate(candidate);
65315
65306
  });
65316
65307
  },
65317
- [domEditSaveTimestampRef, editingPathRef, projectIdRef, persistCandidate]
65308
+ [editingPathRef, projectIdRef, persistCandidate]
65318
65309
  );
65319
65310
  const flushPendingSave = useCallback87(async () => {
65320
65311
  if (saveRafRef.current != null) {
@@ -65326,11 +65317,10 @@ function useEditorSave({
65326
65317
  return inFlightRef.current;
65327
65318
  }
65328
65319
  if (candidate) {
65329
- domEditSaveTimestampRef.current = Date.now();
65330
65320
  return persistCandidate(candidate);
65331
65321
  }
65332
65322
  return await inFlightRef.current ?? { status: "clean" };
65333
- }, [domEditSaveTimestampRef, persistCandidate]);
65323
+ }, [persistCandidate]);
65334
65324
  const discardPendingSave = useCallback87(() => {
65335
65325
  if (saveRafRef.current != null) cancelAnimationFrame(saveRafRef.current);
65336
65326
  saveRafRef.current = null;
@@ -65350,7 +65340,6 @@ function useFileManager({
65350
65340
  projectId,
65351
65341
  showToast,
65352
65342
  recordEdit,
65353
- domEditSaveTimestampRef,
65354
65343
  setRefreshKey
65355
65344
  }) {
65356
65345
  const [editingFile, setEditingFile] = useState103(null);
@@ -65489,7 +65478,6 @@ function useFileManager({
65489
65478
  readProjectFile,
65490
65479
  writeProjectFile,
65491
65480
  recordEdit,
65492
- domEditSaveTimestampRef,
65493
65481
  setRefreshKey,
65494
65482
  showToast
65495
65483
  });
@@ -66286,7 +66274,6 @@ function useRazorSplit({
66286
66274
  writeProjectFile,
66287
66275
  observeProjectFileVersion,
66288
66276
  recordEdit,
66289
- domEditSaveTimestampRef,
66290
66277
  reloadPreview,
66291
66278
  forceReloadSdkSession,
66292
66279
  isRecordingRef
@@ -66314,7 +66301,6 @@ function useRazorSplit({
66314
66301
  const intents = buildAtomicCutIntents(elements, splitTime, activeCompPath);
66315
66302
  const requestedCount = intents.reduce((count, file) => count + file.targets.length, 0);
66316
66303
  const label = mode === "single" ? "Split timeline clip" : `Split ${requestedCount} clips at ${splitTime.toFixed(2)}s`;
66317
- domEditSaveTimestampRef.current = Date.now();
66318
66304
  const result = await runAtomicCutTransaction({
66319
66305
  projectId: pid,
66320
66306
  intents,
@@ -66341,7 +66327,6 @@ function useRazorSplit({
66341
66327
  },
66342
66328
  [
66343
66329
  activeCompPath,
66344
- domEditSaveTimestampRef,
66345
66330
  observeProjectFileVersion,
66346
66331
  recordEdit,
66347
66332
  showToast,
@@ -66461,7 +66446,6 @@ function useTimelineAssetDropOps({
66461
66446
  showToast,
66462
66447
  writeProjectFile,
66463
66448
  recordEdit,
66464
- domEditSaveTimestampRef,
66465
66449
  reloadPreview,
66466
66450
  uploadProjectFiles,
66467
66451
  isRecordingRef,
@@ -66512,7 +66496,6 @@ function useTimelineAssetDropOps({
66512
66496
  )
66513
66497
  })
66514
66498
  );
66515
- domEditSaveTimestampRef.current = Date.now();
66516
66499
  await saveProjectFilesWithHistory({
66517
66500
  projectId: pid,
66518
66501
  label: "Add timeline asset",
@@ -66536,7 +66519,6 @@ function useTimelineAssetDropOps({
66536
66519
  showToast,
66537
66520
  timelineElements,
66538
66521
  writeProjectFile,
66539
- domEditSaveTimestampRef,
66540
66522
  reloadPreview,
66541
66523
  isRecordingRef,
66542
66524
  forceReloadSdkSession
@@ -66596,7 +66578,6 @@ function useTimelineAssetDropOps({
66596
66578
  resync: forceReloadSdkSession,
66597
66579
  refresh: reloadPreview
66598
66580
  });
66599
- domEditSaveTimestampRef.current = Date.now();
66600
66581
  showToast("Composition added to the timeline.", "info");
66601
66582
  } catch (error) {
66602
66583
  showToast(
@@ -66607,7 +66588,6 @@ function useTimelineAssetDropOps({
66607
66588
  },
66608
66589
  [
66609
66590
  activeCompPath,
66610
- domEditSaveTimestampRef,
66611
66591
  forceReloadSdkSession,
66612
66592
  isRecordingRef,
66613
66593
  observeProjectFileVersion,
@@ -66681,7 +66661,6 @@ async function setAudioGroupAttribute({
66681
66661
  previewIframe,
66682
66662
  writeProjectFile,
66683
66663
  recordEdit,
66684
- domEditSaveTimestampRef,
66685
66664
  pendingTimelineEditPathRef
66686
66665
  }) {
66687
66666
  const groupEl = previewIframe?.contentDocument?.getElementById(groupId) ?? null;
@@ -66697,7 +66676,6 @@ async function setAudioGroupAttribute({
66697
66676
  label,
66698
66677
  writeProjectFile,
66699
66678
  recordEdit,
66700
- domEditSaveTimestampRef,
66701
66679
  pendingTimelineEditPathRef,
66702
66680
  patchLive: (v) => patchLiveGroupAttribute(previewIframe, groupId, attr, v)
66703
66681
  });
@@ -66708,7 +66686,6 @@ function useSetAudioGroupAttribute({
66708
66686
  showToast,
66709
66687
  writeProjectFile,
66710
66688
  recordEdit,
66711
- domEditSaveTimestampRef,
66712
66689
  previewIframeRef,
66713
66690
  pendingTimelineEditPathRef,
66714
66691
  isRecordingRef
@@ -66739,7 +66716,6 @@ function useSetAudioGroupAttribute({
66739
66716
  previewIframe: previewIframeRef.current,
66740
66717
  writeProjectFile,
66741
66718
  recordEdit,
66742
- domEditSaveTimestampRef,
66743
66719
  pendingTimelineEditPathRef
66744
66720
  });
66745
66721
  syncStoredGroupAttribute(groupId, attr, value);
@@ -66756,7 +66732,6 @@ function useSetAudioGroupAttribute({
66756
66732
  previewIframeRef,
66757
66733
  writeProjectFile,
66758
66734
  recordEdit,
66759
- domEditSaveTimestampRef,
66760
66735
  pendingTimelineEditPathRef,
66761
66736
  isRecordingRef,
66762
66737
  showToast,
@@ -66784,7 +66759,6 @@ async function setElementAttribute({
66784
66759
  previewIframe,
66785
66760
  writeProjectFile,
66786
66761
  recordEdit,
66787
- domEditSaveTimestampRef,
66788
66762
  pendingTimelineEditPathRef
66789
66763
  }) {
66790
66764
  const targetPath = element.sourceFile || activeCompPath || "index.html";
@@ -66799,7 +66773,6 @@ async function setElementAttribute({
66799
66773
  label,
66800
66774
  writeProjectFile,
66801
66775
  recordEdit,
66802
- domEditSaveTimestampRef,
66803
66776
  pendingTimelineEditPathRef,
66804
66777
  patchLive: (v) => patchLiveElementAttribute(previewIframe, element, attr, v, activeCompPath)
66805
66778
  });
@@ -66810,7 +66783,6 @@ function useSetElementAttribute({
66810
66783
  showToast,
66811
66784
  writeProjectFile,
66812
66785
  recordEdit,
66813
- domEditSaveTimestampRef,
66814
66786
  previewIframeRef,
66815
66787
  pendingTimelineEditPathRef,
66816
66788
  isRecordingRef
@@ -66840,7 +66812,6 @@ function useSetElementAttribute({
66840
66812
  previewIframe: previewIframeRef.current,
66841
66813
  writeProjectFile,
66842
66814
  recordEdit,
66843
- domEditSaveTimestampRef,
66844
66815
  pendingTimelineEditPathRef
66845
66816
  });
66846
66817
  } catch (error) {
@@ -66854,7 +66825,6 @@ function useSetElementAttribute({
66854
66825
  previewIframeRef,
66855
66826
  writeProjectFile,
66856
66827
  recordEdit,
66857
- domEditSaveTimestampRef,
66858
66828
  pendingTimelineEditPathRef,
66859
66829
  isRecordingRef,
66860
66830
  showToast,
@@ -66873,7 +66843,6 @@ function useTimelineDeleteOps({
66873
66843
  showToast,
66874
66844
  writeProjectFile,
66875
66845
  recordEdit,
66876
- domEditSaveTimestampRef,
66877
66846
  reloadPreview,
66878
66847
  isRecordingRef,
66879
66848
  forceReloadSdkSession,
@@ -66926,7 +66895,6 @@ function useTimelineDeleteOps({
66926
66895
  if (deleteContentEnd > 0 && targetPath === (activeCompPath || "index.html")) {
66927
66896
  usePlayerStore.getState().setDuration(deleteContentEnd);
66928
66897
  }
66929
- domEditSaveTimestampRef.current = Date.now();
66930
66898
  try {
66931
66899
  await saveProjectFilesWithHistory({
66932
66900
  projectId: pid,
@@ -66966,7 +66934,6 @@ function useTimelineDeleteOps({
66966
66934
  showToast,
66967
66935
  timelineElements,
66968
66936
  writeProjectFile,
66969
- domEditSaveTimestampRef,
66970
66937
  reloadPreview,
66971
66938
  isRecordingRef,
66972
66939
  forceReloadSdkSession,
@@ -67029,7 +66996,6 @@ async function setElementsHidden({
67029
66996
  previewIframe,
67030
66997
  writeProjectFile,
67031
66998
  recordEdit,
67032
- domEditSaveTimestampRef,
67033
66999
  pendingTimelineEditPathRef
67034
67000
  }) {
67035
67001
  if (elements.length === 0) return [];
@@ -67059,7 +67025,6 @@ async function setElementsHidden({
67059
67025
  files[targetPath] = patchedContent;
67060
67026
  pendingTimelineEditPathRef.current.add(targetPath);
67061
67027
  }
67062
- domEditSaveTimestampRef.current = Date.now();
67063
67028
  const changedPaths = await saveProjectFilesWithHistory({
67064
67029
  projectId,
67065
67030
  label,
@@ -67073,7 +67038,6 @@ async function setElementsHidden({
67073
67038
  writeFile: writeProjectFile,
67074
67039
  recordEdit
67075
67040
  });
67076
- domEditSaveTimestampRef.current = Date.now();
67077
67041
  for (const element of elements) {
67078
67042
  usePlayerStore.getState().updateElement(element.key ?? element.id, { hidden });
67079
67043
  }
@@ -67094,7 +67058,6 @@ async function toggleTimelineTrackHidden({
67094
67058
  previewIframe,
67095
67059
  writeProjectFile,
67096
67060
  recordEdit,
67097
- domEditSaveTimestampRef,
67098
67061
  pendingTimelineEditPathRef
67099
67062
  }) {
67100
67063
  const suffix = trackDisplaySuffix(
@@ -67112,7 +67075,6 @@ async function toggleTimelineTrackHidden({
67112
67075
  previewIframe,
67113
67076
  writeProjectFile,
67114
67077
  recordEdit,
67115
- domEditSaveTimestampRef,
67116
67078
  pendingTimelineEditPathRef
67117
67079
  });
67118
67080
  }
@@ -67125,7 +67087,6 @@ async function toggleTimelineElementHidden({
67125
67087
  previewIframe,
67126
67088
  writeProjectFile,
67127
67089
  recordEdit,
67128
- domEditSaveTimestampRef,
67129
67090
  pendingTimelineEditPathRef
67130
67091
  }) {
67131
67092
  const keys = new Set(typeof elementKey2 === "string" ? [elementKey2] : elementKey2);
@@ -67139,7 +67100,6 @@ async function toggleTimelineElementHidden({
67139
67100
  previewIframe,
67140
67101
  writeProjectFile,
67141
67102
  recordEdit,
67142
- domEditSaveTimestampRef,
67143
67103
  pendingTimelineEditPathRef
67144
67104
  });
67145
67105
  }
@@ -67149,7 +67109,6 @@ function useTimelineTrackVisibilityEditing({
67149
67109
  showToast,
67150
67110
  writeProjectFile,
67151
67111
  recordEdit,
67152
- domEditSaveTimestampRef,
67153
67112
  previewIframeRef,
67154
67113
  pendingTimelineEditPathRef,
67155
67114
  isRecordingRef,
@@ -67175,7 +67134,6 @@ function useTimelineTrackVisibilityEditing({
67175
67134
  previewIframe: previewIframeRef.current,
67176
67135
  writeProjectFile,
67177
67136
  recordEdit,
67178
- domEditSaveTimestampRef,
67179
67137
  pendingTimelineEditPathRef
67180
67138
  });
67181
67139
  forceReloadSdkSession?.();
@@ -67191,7 +67149,6 @@ function useTimelineTrackVisibilityEditing({
67191
67149
  previewIframeRef,
67192
67150
  writeProjectFile,
67193
67151
  recordEdit,
67194
- domEditSaveTimestampRef,
67195
67152
  pendingTimelineEditPathRef,
67196
67153
  isRecordingRef,
67197
67154
  showToast,
@@ -67206,7 +67163,6 @@ function useTimelineElementVisibilityEditing({
67206
67163
  showToast,
67207
67164
  writeProjectFile,
67208
67165
  recordEdit,
67209
- domEditSaveTimestampRef,
67210
67166
  previewIframeRef,
67211
67167
  pendingTimelineEditPathRef,
67212
67168
  isRecordingRef,
@@ -67231,7 +67187,6 @@ function useTimelineElementVisibilityEditing({
67231
67187
  previewIframe: previewIframeRef.current,
67232
67188
  writeProjectFile,
67233
67189
  recordEdit,
67234
- domEditSaveTimestampRef,
67235
67190
  pendingTimelineEditPathRef
67236
67191
  });
67237
67192
  forceReloadSdkSession?.();
@@ -67247,7 +67202,6 @@ function useTimelineElementVisibilityEditing({
67247
67202
  previewIframeRef,
67248
67203
  writeProjectFile,
67249
67204
  recordEdit,
67250
- domEditSaveTimestampRef,
67251
67205
  pendingTimelineEditPathRef,
67252
67206
  isRecordingRef,
67253
67207
  showToast,
@@ -67314,7 +67268,6 @@ async function createAudioGroupAndAssignMembers({
67314
67268
  previewIframe,
67315
67269
  writeProjectFile,
67316
67270
  recordEdit,
67317
- domEditSaveTimestampRef,
67318
67271
  pendingTimelineEditPathRef
67319
67272
  }) {
67320
67273
  if (elements.length < 2) {
@@ -67362,7 +67315,6 @@ async function createAudioGroupAndAssignMembers({
67362
67315
  files[groupPath] = withGroupElement;
67363
67316
  pendingTimelineEditPathRef.current.add(groupPath);
67364
67317
  }
67365
- domEditSaveTimestampRef.current = Date.now();
67366
67318
  const changedPaths = await saveProjectFilesWithHistory({
67367
67319
  projectId,
67368
67320
  label: groupLabel2 ? `Group ${elements.length} clips as ${groupLabel2}` : `Group ${elements.length} voice clips`,
@@ -67376,7 +67328,6 @@ async function createAudioGroupAndAssignMembers({
67376
67328
  writeFile: writeProjectFile,
67377
67329
  recordEdit
67378
67330
  });
67379
- domEditSaveTimestampRef.current = Date.now();
67380
67331
  for (const element of elements) {
67381
67332
  usePlayerStore.getState().updateElement(element.key ?? element.id, { audioGroup: groupId });
67382
67333
  }
@@ -67396,7 +67347,6 @@ function useAudioGroupCarveAssignment({
67396
67347
  showToast,
67397
67348
  writeProjectFile,
67398
67349
  recordEdit,
67399
- domEditSaveTimestampRef,
67400
67350
  previewIframeRef,
67401
67351
  pendingTimelineEditPathRef,
67402
67352
  isRecordingRef
@@ -67431,7 +67381,6 @@ function useAudioGroupCarveAssignment({
67431
67381
  previewIframe: previewIframeRef.current,
67432
67382
  writeProjectFile,
67433
67383
  recordEdit,
67434
- domEditSaveTimestampRef,
67435
67384
  pendingTimelineEditPathRef
67436
67385
  });
67437
67386
  } catch (error) {
@@ -67447,7 +67396,6 @@ function useAudioGroupCarveAssignment({
67447
67396
  previewIframeRef,
67448
67397
  writeProjectFile,
67449
67398
  recordEdit,
67450
- domEditSaveTimestampRef,
67451
67399
  pendingTimelineEditPathRef,
67452
67400
  isRecordingRef,
67453
67401
  showToast,
@@ -67482,7 +67430,6 @@ function resizeHasPlaybackStartAdjustment(change) {
67482
67430
  }
67483
67431
  function useTimelineGroupEditing({
67484
67432
  activeCompPath,
67485
- domEditSaveTimestampRef,
67486
67433
  editQueueRef,
67487
67434
  forceReloadSdkSession,
67488
67435
  invalidateGsapCache,
@@ -67525,7 +67472,6 @@ function useTimelineGroupEditing({
67525
67472
  changes: batchChanges,
67526
67473
  writeProjectFile,
67527
67474
  recordEdit,
67528
- domEditSaveTimestampRef,
67529
67475
  pendingTimelineEditPathRef,
67530
67476
  coalesceKey,
67531
67477
  coalesceMs
@@ -67534,7 +67480,6 @@ function useTimelineGroupEditing({
67534
67480
  },
67535
67481
  [
67536
67482
  activeCompPath,
67537
- domEditSaveTimestampRef,
67538
67483
  forceReloadSdkSession,
67539
67484
  pendingTimelineEditPathRef,
67540
67485
  recordEdit,
@@ -67554,7 +67499,6 @@ function useTimelineGroupEditing({
67554
67499
  editHistory: { recordEdit },
67555
67500
  writeProjectFile,
67556
67501
  reloadPreview,
67557
- domEditSaveTimestampRef,
67558
67502
  compositionPath: activeCompPath,
67559
67503
  readProjectFile: (path) => readFileContent(projectIdRef.current ?? "", path),
67560
67504
  publishSession: publishSdkSession
@@ -67570,7 +67514,6 @@ function useTimelineGroupEditing({
67570
67514
  },
67571
67515
  [
67572
67516
  activeCompPath,
67573
- domEditSaveTimestampRef,
67574
67517
  projectIdRef,
67575
67518
  publishSdkSession,
67576
67519
  recordEdit,
@@ -67794,7 +67737,6 @@ function useTimelineEditing({
67794
67737
  writeProjectFile,
67795
67738
  observeProjectFileVersion,
67796
67739
  recordEdit,
67797
- domEditSaveTimestampRef,
67798
67740
  reloadPreview,
67799
67741
  previewIframeRef,
67800
67742
  pendingTimelineEditPathRef,
@@ -67826,7 +67768,6 @@ function useTimelineEditing({
67826
67768
  buildPatches,
67827
67769
  writeProjectFile,
67828
67770
  recordEdit,
67829
- domEditSaveTimestampRef,
67830
67771
  pendingTimelineEditPathRef,
67831
67772
  coalesceKey
67832
67773
  })
@@ -67842,7 +67783,6 @@ function useTimelineEditing({
67842
67783
  activeCompPath,
67843
67784
  recordEdit,
67844
67785
  writeProjectFile,
67845
- domEditSaveTimestampRef,
67846
67786
  pendingTimelineEditPathRef,
67847
67787
  showToast,
67848
67788
  isRecordingRef,
@@ -67851,7 +67791,6 @@ function useTimelineEditing({
67851
67791
  );
67852
67792
  const groupEditing = useTimelineGroupEditing({
67853
67793
  activeCompPath,
67854
- domEditSaveTimestampRef,
67855
67794
  editQueueRef,
67856
67795
  forceReloadSdkSession,
67857
67796
  invalidateGsapCache,
@@ -67936,7 +67875,6 @@ function useTimelineEditing({
67936
67875
  editHistory: { recordEdit },
67937
67876
  writeProjectFile,
67938
67877
  reloadPreview,
67939
- domEditSaveTimestampRef,
67940
67878
  compositionPath: activeCompPath,
67941
67879
  // Capture on-disk bytes as the undo `before` so undoing a timing move
67942
67880
  // restores the file verbatim, not a normalized full-DOM re-emit.
@@ -67967,7 +67905,6 @@ function useTimelineEditing({
67967
67905
  recordEdit,
67968
67906
  writeProjectFile,
67969
67907
  reloadPreview,
67970
- domEditSaveTimestampRef,
67971
67908
  timelineElements,
67972
67909
  handleDomZIndexReorderCommitRef,
67973
67910
  showToast,
@@ -68022,7 +67959,6 @@ function useTimelineEditing({
68022
67959
  editHistory: { recordEdit },
68023
67960
  writeProjectFile,
68024
67961
  reloadPreview,
68025
- domEditSaveTimestampRef,
68026
67962
  compositionPath: activeCompPath,
68027
67963
  // Capture on-disk bytes as the undo `before` so undoing a timing
68028
67964
  // resize restores the file verbatim, not a normalized full-DOM re-emit.
@@ -68049,7 +67985,6 @@ function useTimelineEditing({
68049
67985
  recordEdit,
68050
67986
  writeProjectFile,
68051
67987
  reloadPreview,
68052
- domEditSaveTimestampRef,
68053
67988
  showToast,
68054
67989
  invalidateGsapCache
68055
67990
  ]
@@ -68061,7 +67996,6 @@ function useTimelineEditing({
68061
67996
  showToast,
68062
67997
  writeProjectFile,
68063
67998
  recordEdit,
68064
- domEditSaveTimestampRef,
68065
67999
  previewIframeRef,
68066
68000
  pendingTimelineEditPathRef,
68067
68001
  isRecordingRef,
@@ -68073,7 +68007,6 @@ function useTimelineEditing({
68073
68007
  showToast,
68074
68008
  writeProjectFile,
68075
68009
  recordEdit,
68076
- domEditSaveTimestampRef,
68077
68010
  previewIframeRef,
68078
68011
  pendingTimelineEditPathRef,
68079
68012
  isRecordingRef,
@@ -68085,7 +68018,6 @@ function useTimelineEditing({
68085
68018
  showToast,
68086
68019
  writeProjectFile,
68087
68020
  recordEdit,
68088
- domEditSaveTimestampRef,
68089
68021
  previewIframeRef,
68090
68022
  pendingTimelineEditPathRef,
68091
68023
  isRecordingRef
@@ -68096,7 +68028,6 @@ function useTimelineEditing({
68096
68028
  showToast,
68097
68029
  writeProjectFile,
68098
68030
  recordEdit,
68099
- domEditSaveTimestampRef,
68100
68031
  previewIframeRef,
68101
68032
  pendingTimelineEditPathRef,
68102
68033
  isRecordingRef
@@ -68107,7 +68038,6 @@ function useTimelineEditing({
68107
68038
  showToast,
68108
68039
  writeProjectFile,
68109
68040
  recordEdit,
68110
- domEditSaveTimestampRef,
68111
68041
  previewIframeRef,
68112
68042
  pendingTimelineEditPathRef,
68113
68043
  isRecordingRef
@@ -68119,7 +68049,6 @@ function useTimelineEditing({
68119
68049
  showToast,
68120
68050
  writeProjectFile,
68121
68051
  recordEdit,
68122
- domEditSaveTimestampRef,
68123
68052
  reloadPreview,
68124
68053
  isRecordingRef,
68125
68054
  forceReloadSdkSession,
@@ -68132,7 +68061,6 @@ function useTimelineEditing({
68132
68061
  showToast,
68133
68062
  writeProjectFile,
68134
68063
  recordEdit,
68135
- domEditSaveTimestampRef,
68136
68064
  reloadPreview,
68137
68065
  uploadProjectFiles,
68138
68066
  isRecordingRef,
@@ -68147,7 +68075,6 @@ function useTimelineEditing({
68147
68075
  writeProjectFile,
68148
68076
  observeProjectFileVersion,
68149
68077
  recordEdit,
68150
- domEditSaveTimestampRef,
68151
68078
  reloadPreview,
68152
68079
  isRecordingRef,
68153
68080
  forceReloadSdkSession
@@ -68930,7 +68857,7 @@ function usePreviewInteraction({
68930
68857
  const wasPlaying = usePlayerStore.getState().isPlaying;
68931
68858
  pausePreviewPlayback();
68932
68859
  const resumeIfNothingSelected = () => {
68933
- if (wasPlaying) usePlayerStore.getState().setIsPlaying(true);
68860
+ if (wasPlaying) usePlayerStore.getState().requestPlayback(true);
68934
68861
  };
68935
68862
  if (isDoubleClick && !e.shiftKey) {
68936
68863
  const hit = await resolveDomSelectionFromPreviewPoint(e.clientX, e.clientY);
@@ -70481,7 +70408,6 @@ function useDomEditCommits({
70481
70408
  showToast,
70482
70409
  queueDomEditSave,
70483
70410
  writeProjectFile,
70484
- domEditSaveTimestampRef,
70485
70411
  editHistory,
70486
70412
  fileTree,
70487
70413
  importedFontAssetsRef,
@@ -70571,7 +70497,6 @@ function useDomEditCommits({
70571
70497
  );
70572
70498
  }
70573
70499
  }
70574
- domEditSaveTimestampRef.current = Date.now();
70575
70500
  const patchResponse = await fetch(
70576
70501
  buildProjectApiPath(pid, `/file-mutations/patch-element/${encodeURIComponent(targetPath)}`),
70577
70502
  {
@@ -70644,7 +70569,6 @@ function useDomEditCommits({
70644
70569
  editHistory,
70645
70570
  writeProjectFile,
70646
70571
  projectIdRef,
70647
- domEditSaveTimestampRef,
70648
70572
  reloadPreview,
70649
70573
  showToast,
70650
70574
  forceReloadSdkSession,
@@ -70685,7 +70609,6 @@ function useDomEditCommits({
70685
70609
  { alreadyToasted: true }
70686
70610
  );
70687
70611
  }
70688
- domEditSaveTimestampRef.current = Date.now();
70689
70612
  const atomicResult = await patchElementBatches(pid, batches);
70690
70613
  const allMatched = atomicResult.durable && atomicResult.files.every((result) => result.allMatched);
70691
70614
  const files = Object.fromEntries(
@@ -70723,15 +70646,7 @@ function useDomEditCommits({
70723
70646
  throw error;
70724
70647
  });
70725
70648
  },
70726
- [
70727
- domEditSaveTimestampRef,
70728
- editHistory,
70729
- forceReloadSdkSession,
70730
- projectIdRef,
70731
- queueDomEditSave,
70732
- reloadPreview,
70733
- showToast
70734
- ]
70649
+ [editHistory, forceReloadSdkSession, projectIdRef, queueDomEditSave, reloadPreview, showToast]
70735
70650
  );
70736
70651
  const {
70737
70652
  handleDomStyleCommit,
@@ -70778,7 +70693,6 @@ function useDomEditCommits({
70778
70693
  activeCompPath,
70779
70694
  showToast,
70780
70695
  writeProjectFile,
70781
- domEditSaveTimestampRef,
70782
70696
  editHistory,
70783
70697
  projectIdRef,
70784
70698
  reloadPreview,
@@ -70836,7 +70750,6 @@ function computeGroupGeometry(members) {
70836
70750
  }
70837
70751
  async function commitStructuralMutation(pid, targetPath, route, body, label, deps) {
70838
70752
  const originalContent = await readProjectFileContent(pid, targetPath);
70839
- deps.domEditSaveTimestampRef.current = Date.now();
70840
70753
  const mutateResponse = await fetch(
70841
70754
  buildProjectApiPath(pid, `/file-mutations/${route}/${encodeURIComponent(targetPath)}`),
70842
70755
  {
@@ -72162,7 +72075,7 @@ function instantPatchesFor(options) {
72162
72075
  ...options.instantPatch ? [options.instantPatch] : []
72163
72076
  ];
72164
72077
  }
72165
- function useGsapScriptCommits({ projectIdRef, activeCompPath, previewIframeRef, editHistory, domEditSaveTimestampRef, reloadPreview, onCacheInvalidate, onFileContentChanged, showToast, sdkSession, publishSdkSession, writeProjectFile, forceReloadSdkSession }) {
72078
+ function useGsapScriptCommits({ projectIdRef, activeCompPath, previewIframeRef, editHistory, reloadPreview, onCacheInvalidate, onFileContentChanged, showToast, sdkSession, publishSdkSession, writeProjectFile, forceReloadSdkSession }) {
72166
72079
  const activeProjectId = projectIdRef.current;
72167
72080
  const activeCompPathRef = useRef127(activeCompPath);
72168
72081
  activeCompPathRef.current = activeCompPath;
@@ -72191,7 +72104,6 @@ function useGsapScriptCommits({ projectIdRef, activeCompPath, previewIframeRef,
72191
72104
  }
72192
72105
  return;
72193
72106
  }
72194
- if (previewIsActive) domEditSaveTimestampRef.current = Date.now();
72195
72107
  await recordMutationEdit(targetPath, result, options);
72196
72108
  if (!isActiveCommitTarget(projectIdRef, activeCompPathRef, projectId, compositionPath)) return;
72197
72109
  syncCommittedGsapMutation({
@@ -72206,7 +72118,7 @@ function useGsapScriptCommits({ projectIdRef, activeCompPath, previewIframeRef,
72206
72118
  reloadPreview,
72207
72119
  onCacheInvalidate
72208
72120
  });
72209
- }, [projectIdRef, previewIframeRef, domEditSaveTimestampRef, reloadPreview, onCacheInvalidate, onFileContentChanged, forceReloadSdkSession, recordMutationEdit]);
72121
+ }, [projectIdRef, previewIframeRef, reloadPreview, onCacheInvalidate, onFileContentChanged, forceReloadSdkSession, recordMutationEdit]);
72210
72122
  const runCommit = useCallback115(async (pid, compositionPath, targetPath, selection, mutation, options) => {
72211
72123
  const result = await runMutationRequest(
72212
72124
  [mutation],
@@ -72305,7 +72217,6 @@ function useGsapScriptCommits({ projectIdRef, activeCompPath, previewIframeRef,
72305
72217
  editHistory: { recordEdit: editHistory.recordEdit },
72306
72218
  writeProjectFile,
72307
72219
  reloadPreview,
72308
- domEditSaveTimestampRef,
72309
72220
  refresh: sdkRefresh,
72310
72221
  compositionPath: activeCompPath,
72311
72222
  readProjectFile: readProjectFileContent2,
@@ -72315,7 +72226,6 @@ function useGsapScriptCommits({ projectIdRef, activeCompPath, previewIframeRef,
72315
72226
  editHistory.recordEdit,
72316
72227
  writeProjectFile,
72317
72228
  reloadPreview,
72318
- domEditSaveTimestampRef,
72319
72229
  sdkRefresh,
72320
72230
  activeCompPath,
72321
72231
  readProjectFileContent2,
@@ -74216,7 +74126,6 @@ function useDomEditSession({
74216
74126
  readProjectFile,
74217
74127
  writeProjectFile,
74218
74128
  updateEditingFileContent,
74219
- domEditSaveTimestampRef,
74220
74129
  editHistory,
74221
74130
  fileTree,
74222
74131
  importedFontAssetsRef,
@@ -74329,7 +74238,6 @@ function useDomEditSession({
74329
74238
  activeCompPath,
74330
74239
  previewIframeRef,
74331
74240
  editHistory,
74332
- domEditSaveTimestampRef,
74333
74241
  reloadPreview,
74334
74242
  onCacheInvalidate: bumpGsapCache,
74335
74243
  onFileContentChanged: updateEditingFileContent,
@@ -74364,7 +74272,6 @@ function useDomEditSession({
74364
74272
  showToast,
74365
74273
  queueDomEditSave,
74366
74274
  writeProjectFile,
74367
- domEditSaveTimestampRef,
74368
74275
  editHistory,
74369
74276
  fileTree,
74370
74277
  importedFontAssetsRef,
@@ -74392,7 +74299,6 @@ function useDomEditSession({
74392
74299
  editHistory,
74393
74300
  writeProjectFile,
74394
74301
  reloadPreview,
74395
- domEditSaveTimestampRef,
74396
74302
  compositionPath: activeCompPath,
74397
74303
  readProjectFile,
74398
74304
  publishSession: publishSdkSession
@@ -74404,7 +74310,6 @@ function useDomEditSession({
74404
74310
  editHistory,
74405
74311
  writeProjectFile,
74406
74312
  reloadPreview,
74407
- domEditSaveTimestampRef,
74408
74313
  compositionPath: activeCompPath,
74409
74314
  readProjectFile,
74410
74315
  publishSession: publishSdkSession
@@ -74423,7 +74328,6 @@ function useDomEditSession({
74423
74328
  activeCompPath,
74424
74329
  showToast,
74425
74330
  writeProjectFile,
74426
- domEditSaveTimestampRef,
74427
74331
  editHistory,
74428
74332
  projectIdRef,
74429
74333
  reloadPreview,
@@ -74955,23 +74859,23 @@ function testHotAdapter() {
74955
74859
  const candidate = value;
74956
74860
  return typeof candidate.on === "function" && typeof candidate.off === "function" ? candidate : null;
74957
74861
  }
74958
- function readFileChangeContent(payload) {
74959
- if (!payload || typeof payload !== "object") return null;
74960
- const record = payload;
74961
- if (typeof record.content === "string") return record.content;
74962
- return "data" in record ? readFileChangeContent(record.data) : null;
74963
- }
74964
- function readFileChangeVersion(payload) {
74965
- if (!payload || typeof payload !== "object") return null;
74966
- const record = payload;
74967
- if (typeof record.version === "string") return record.version;
74968
- return "data" in record ? readFileChangeVersion(record.data) : null;
74862
+ var readFileChangeContent = (payload) => readFileChangeField(payload, "content");
74863
+ var readFileChangeVersion = (payload) => readFileChangeField(payload, "version");
74864
+ var readFileChangeWriteToken = (payload) => readFileChangeField(payload, "writeToken");
74865
+ function decodeFileChange(delivery) {
74866
+ const data = delivery?.data;
74867
+ if (typeof data !== "string") return delivery;
74868
+ try {
74869
+ return JSON.parse(data);
74870
+ } catch {
74871
+ logReload("file-change", { path: null, why: "unparseable payload" });
74872
+ return null;
74873
+ }
74969
74874
  }
74970
- function readFileChangeWriteToken(payload) {
74971
- if (!payload || typeof payload !== "object") return null;
74972
- const record = payload;
74973
- if (typeof record.writeToken === "string") return record.writeToken;
74974
- return "data" in record ? readFileChangeWriteToken(record.data) : null;
74875
+ function sseFileChangeChannel(onDelivery) {
74876
+ const eventSource = new EventSource("/api/events");
74877
+ eventSource.addEventListener("file-change", onDelivery);
74878
+ return () => eventSource.close();
74975
74879
  }
74976
74880
  function eventIdentity(path, payload) {
74977
74881
  const version = readFileChangeVersion(payload);
@@ -75184,7 +75088,10 @@ function useExternalFileChangeCoordinator({
75184
75088
  // fallow-ignore-next-line complexity
75185
75089
  (payload) => {
75186
75090
  const path = readStudioFileChangePath(payload);
75187
- if (!path || !projectId) return;
75091
+ if (!path || !projectId) {
75092
+ logReload("file-change", { path: null, why: path ? "no project" : "no path in payload" });
75093
+ return;
75094
+ }
75188
75095
  pendingTimelineEditPathRef.current.delete(path);
75189
75096
  const content = readFileChangeContent(payload);
75190
75097
  const token = readFileChangeWriteToken(payload);
@@ -75211,7 +75118,7 @@ function useExternalFileChangeCoordinator({
75211
75118
  [projectId, pendingTimelineEditPathRef, startDrainLoop, onAcceptedPersistedFileChange]
75212
75119
  );
75213
75120
  useEffect106(() => {
75214
- const handler = (payload) => processChange(payload);
75121
+ const handler = (delivery) => processChange(decodeFileChange(delivery));
75215
75122
  const adapter = testHotAdapter();
75216
75123
  if (adapter) {
75217
75124
  adapter.on("hf:file-change", handler);
@@ -75221,9 +75128,7 @@ function useExternalFileChangeCoordinator({
75221
75128
  import.meta.hot.on("hf:file-change", handler);
75222
75129
  return () => import.meta.hot?.off?.("hf:file-change", handler);
75223
75130
  }
75224
- const eventSource = new EventSource("/api/events");
75225
- eventSource.addEventListener("file-change", handler);
75226
- return () => eventSource.close();
75131
+ return sseFileChangeChannel(handler);
75227
75132
  }, [processChange]);
75228
75133
  const retry = useCallback125(async () => {
75229
75134
  const current = blockedRef.current;
@@ -75873,7 +75778,6 @@ function useAppHotkeys({
75873
75778
  readOptionalProjectFile,
75874
75779
  readProjectFile,
75875
75780
  writeProjectFile,
75876
- domEditSaveTimestampRef,
75877
75781
  showToast,
75878
75782
  syncHistoryPreviewAfterApply,
75879
75783
  waitForPendingDomEditSaves,
@@ -75897,10 +75801,9 @@ function useAppHotkeys({
75897
75801
  );
75898
75802
  const writeHistoryFile = useCallback128(
75899
75803
  async (path, content) => {
75900
- domEditSaveTimestampRef.current = Date.now();
75901
75804
  await writeProjectFile(path, content);
75902
75805
  },
75903
- [domEditSaveTimestampRef, writeProjectFile]
75806
+ [writeProjectFile]
75904
75807
  );
75905
75808
  const serializeHistoryFiles = useCallback128(
75906
75809
  (paths, task) => serializeStudioFileMutations(writeProjectFile, paths, task),
@@ -76136,7 +76039,6 @@ function useClipboard({
76136
76039
  showToast,
76137
76040
  writeProjectFile,
76138
76041
  recordEdit,
76139
- domEditSaveTimestampRef,
76140
76042
  reloadPreview,
76141
76043
  handleTimelineElementDelete,
76142
76044
  handleDomEditElementDelete,
@@ -76231,7 +76133,6 @@ function useClipboard({
76231
76133
  payload.originSelectorIndex
76232
76134
  );
76233
76135
  }
76234
- domEditSaveTimestampRef.current = Date.now();
76235
76136
  await saveProjectFilesWithHistory({
76236
76137
  projectId: pid,
76237
76138
  label: payload.kind === "timeline-clip" ? "Paste clip" : "Paste element",
@@ -76247,14 +76148,7 @@ function useClipboard({
76247
76148
  const message = error instanceof Error ? error.message : "Failed to paste";
76248
76149
  showToast(message);
76249
76150
  }
76250
- }, [
76251
- activeCompPath,
76252
- domEditSaveTimestampRef,
76253
- recordEdit,
76254
- reloadPreview,
76255
- showToast,
76256
- writeProjectFile
76257
- ]);
76151
+ }, [activeCompPath, recordEdit, reloadPreview, showToast, writeProjectFile]);
76258
76152
  const handleCut = useCallback129(async () => {
76259
76153
  const copied = handleCopy2();
76260
76154
  if (!copied) return false;
@@ -85277,7 +85171,6 @@ function useVariablesPersist({
85277
85171
  writeProjectFile,
85278
85172
  recordEdit,
85279
85173
  reloadPreview,
85280
- domEditSaveTimestampRef,
85281
85174
  publishSdkSession
85282
85175
  }) {
85283
85176
  return useCallback160(
@@ -85293,7 +85186,6 @@ function useVariablesPersist({
85293
85186
  editHistory: { recordEdit },
85294
85187
  writeProjectFile,
85295
85188
  reloadPreview,
85296
- domEditSaveTimestampRef,
85297
85189
  compositionPath: activeCompPath,
85298
85190
  readProjectFile,
85299
85191
  publishSession: publishSdkSession
@@ -85310,7 +85202,6 @@ function useVariablesPersist({
85310
85202
  writeProjectFile,
85311
85203
  recordEdit,
85312
85204
  reloadPreview,
85313
- domEditSaveTimestampRef,
85314
85205
  publishSdkSession
85315
85206
  ]
85316
85207
  );
@@ -85362,7 +85253,7 @@ function useProjectCompositionVariables(fileTree, excludePath, readProjectFile,
85362
85253
  return groups;
85363
85254
  }
85364
85255
  function useEditVariablesInFile(deps) {
85365
- const { readProjectFile, writeProjectFile, recordEdit, reloadPreview, domEditSaveTimestampRef } = deps;
85256
+ const { readProjectFile, writeProjectFile, recordEdit, reloadPreview } = deps;
85366
85257
  return useCallback161(
85367
85258
  async (path, label, mutate) => {
85368
85259
  const originalContent = await readProjectFile(path);
@@ -85382,14 +85273,13 @@ function useEditVariablesInFile(deps) {
85382
85273
  editHistory: { recordEdit },
85383
85274
  writeProjectFile,
85384
85275
  reloadPreview,
85385
- domEditSaveTimestampRef,
85386
85276
  compositionPath: path,
85387
85277
  readProjectFile
85388
85278
  },
85389
85279
  { label }
85390
85280
  );
85391
85281
  },
85392
- [readProjectFile, writeProjectFile, recordEdit, reloadPreview, domEditSaveTimestampRef]
85282
+ [readProjectFile, writeProjectFile, recordEdit, reloadPreview]
85393
85283
  );
85394
85284
  }
85395
85285
 
@@ -85725,8 +85615,7 @@ function VariablesOtherCompositions({
85725
85615
  readProjectFile,
85726
85616
  writeProjectFile,
85727
85617
  recordEdit,
85728
- reloadPreview,
85729
- domEditSaveTimestampRef
85618
+ reloadPreview
85730
85619
  }) {
85731
85620
  const [selfRefresh, setSelfRefresh] = useState144(0);
85732
85621
  const groups = useProjectCompositionVariables(
@@ -85739,8 +85628,7 @@ function VariablesOtherCompositions({
85739
85628
  readProjectFile,
85740
85629
  writeProjectFile,
85741
85630
  recordEdit,
85742
- reloadPreview,
85743
- domEditSaveTimestampRef
85631
+ reloadPreview
85744
85632
  });
85745
85633
  const [editingKey, setEditingKey] = useState144(null);
85746
85634
  const onSave = useCallback162(
@@ -85943,7 +85831,6 @@ var VariablesPanel = memo51(function VariablesPanel2({
85943
85831
  sdkSession,
85944
85832
  publishSdkSession,
85945
85833
  reloadPreview,
85946
- domEditSaveTimestampRef,
85947
85834
  recordEdit
85948
85835
  }) {
85949
85836
  const { activeCompPath, showToast } = useStudioShellContext();
@@ -85967,7 +85854,6 @@ var VariablesPanel = memo51(function VariablesPanel2({
85967
85854
  writeProjectFile,
85968
85855
  recordEdit,
85969
85856
  reloadPreview,
85970
- domEditSaveTimestampRef,
85971
85857
  publishSdkSession
85972
85858
  });
85973
85859
  const declarations = useMemo72(
@@ -86202,8 +86088,7 @@ var VariablesPanel = memo51(function VariablesPanel2({
86202
86088
  readProjectFile,
86203
86089
  writeProjectFile,
86204
86090
  recordEdit,
86205
- reloadPreview,
86206
- domEditSaveTimestampRef
86091
+ reloadPreview
86207
86092
  }
86208
86093
  )
86209
86094
  ] })
@@ -86285,7 +86170,6 @@ function useSlideshowPersist({
86285
86170
  writeProjectFile,
86286
86171
  recordEdit,
86287
86172
  reloadPreview,
86288
- domEditSaveTimestampRef,
86289
86173
  publishSdkSession,
86290
86174
  coalesceKey
86291
86175
  }) {
@@ -86302,7 +86186,6 @@ function useSlideshowPersist({
86302
86186
  editHistory: { recordEdit },
86303
86187
  writeProjectFile,
86304
86188
  reloadPreview,
86305
- domEditSaveTimestampRef,
86306
86189
  readProjectFile,
86307
86190
  publishSession: publishSdkSession
86308
86191
  },
@@ -86316,7 +86199,6 @@ function useSlideshowPersist({
86316
86199
  writeProjectFile,
86317
86200
  recordEdit,
86318
86201
  reloadPreview,
86319
- domEditSaveTimestampRef,
86320
86202
  publishSdkSession,
86321
86203
  coalesceKey
86322
86204
  ]
@@ -86572,7 +86454,6 @@ async function applyColorGradingScopeUpdate({
86572
86454
  selectedSourceFile,
86573
86455
  fileTree,
86574
86456
  projectId,
86575
- domEditSaveTimestampRef,
86576
86457
  waitForPendingDomEditSaves,
86577
86458
  readProjectFile,
86578
86459
  writeProjectFile,
@@ -86597,7 +86478,6 @@ async function applyColorGradingScopeUpdate({
86597
86478
  showToast("No color grading changed", "info");
86598
86479
  return EMPTY_COLOR_GRADING_SCOPE_RESULT;
86599
86480
  }
86600
- domEditSaveTimestampRef.current = Date.now();
86601
86481
  const changedPaths = await saveProjectFilesWithHistory({
86602
86482
  projectId,
86603
86483
  label: value ? "Apply color grading" : "Clear color grading",
@@ -86719,7 +86599,6 @@ function StudioRightPanel({
86719
86599
  publishSdkSession,
86720
86600
  forceReloadSdkSession,
86721
86601
  reloadPreview,
86722
- domEditSaveTimestampRef,
86723
86602
  recordEdit,
86724
86603
  onToggleElementHidden,
86725
86604
  onAutoGroupCarveSources,
@@ -86810,7 +86689,6 @@ function StudioRightPanel({
86810
86689
  writeProjectFile,
86811
86690
  recordEdit,
86812
86691
  reloadPreview,
86813
- domEditSaveTimestampRef,
86814
86692
  publishSdkSession
86815
86693
  });
86816
86694
  const onPersistSlideshowNotes = useSlideshowPersist({
@@ -86820,7 +86698,6 @@ function StudioRightPanel({
86820
86698
  writeProjectFile,
86821
86699
  recordEdit,
86822
86700
  reloadPreview,
86823
- domEditSaveTimestampRef,
86824
86701
  publishSdkSession,
86825
86702
  coalesceKey: activeCompPath ? `slideshow-notes:${activeCompPath}` : "slideshow-notes"
86826
86703
  });
@@ -86860,7 +86737,6 @@ function StudioRightPanel({
86860
86737
  selectedSourceFile: domEditSelection?.sourceFile || activeCompPath || "index.html",
86861
86738
  fileTree,
86862
86739
  projectId,
86863
- domEditSaveTimestampRef,
86864
86740
  waitForPendingDomEditSaves,
86865
86741
  readProjectFile,
86866
86742
  writeProjectFile,
@@ -86876,7 +86752,6 @@ function StudioRightPanel({
86876
86752
  }),
86877
86753
  [
86878
86754
  activeCompPath,
86879
- domEditSaveTimestampRef,
86880
86755
  domEditSelection?.sourceFile,
86881
86756
  fileTree,
86882
86757
  projectId,
@@ -86913,7 +86788,6 @@ function StudioRightPanel({
86913
86788
  writeProjectFile,
86914
86789
  recordEdit,
86915
86790
  reloadPreview,
86916
- domEditSaveTimestampRef,
86917
86791
  forceReloadSharedSdkSession: forceReloadSdkSession,
86918
86792
  children: /* @__PURE__ */ jsx205(
86919
86793
  PropertyPanel,
@@ -87086,7 +86960,6 @@ function StudioRightPanel({
87086
86960
  sdkSession,
87087
86961
  publishSdkSession,
87088
86962
  reloadPreview,
87089
- domEditSaveTimestampRef,
87090
86963
  recordEdit
87091
86964
  }
87092
86965
  ) : layersPaneOpen && designPaneOpen && !STUDIO_FLAT_INSPECTOR_ENABLED ? /* @__PURE__ */ jsxs170("div", { ref: splitContainerRef, className: "flex h-full min-h-0 min-w-0 flex-col", children: [
@@ -89596,7 +89469,6 @@ function StudioApp() {
89596
89469
  rightPanelTab: initialUrlStateRef.current.rightPanelTab
89597
89470
  });
89598
89471
  const editHistory = usePersistentEditHistory({ projectId });
89599
- const domEditSaveTimestampRef = useRef171(0);
89600
89472
  const handleDomZIndexReorderCommitRef = useRef171(null);
89601
89473
  const pendingTimelineEditPathRef = useRef171(/* @__PURE__ */ new Set());
89602
89474
  const isGestureRecordingRef = useRef171(false);
@@ -89605,7 +89477,6 @@ function StudioApp() {
89605
89477
  projectId,
89606
89478
  showToast,
89607
89479
  recordEdit: editHistory.recordEdit,
89608
- domEditSaveTimestampRef,
89609
89480
  setRefreshKey
89610
89481
  });
89611
89482
  const masterCompPath = useMemo77(
@@ -89654,7 +89525,6 @@ function StudioApp() {
89654
89525
  writeProjectFile: fileManager.writeProjectFile,
89655
89526
  observeProjectFileVersion: fileManager.observeProjectFileVersion,
89656
89527
  recordEdit: editHistory.recordEdit,
89657
- domEditSaveTimestampRef,
89658
89528
  reloadPreview,
89659
89529
  previewIframeRef,
89660
89530
  pendingTimelineEditPathRef,
@@ -89719,7 +89589,6 @@ function StudioApp() {
89719
89589
  showToast,
89720
89590
  writeProjectFile: fileManager.writeProjectFile,
89721
89591
  recordEdit: editHistory.recordEdit,
89722
- domEditSaveTimestampRef,
89723
89592
  reloadPreview,
89724
89593
  handleTimelineElementDelete: timelineEditing.handleTimelineElementDelete,
89725
89594
  handleDomEditElementDelete: domEditDeleteBridge,
@@ -89735,7 +89604,6 @@ function StudioApp() {
89735
89604
  readOptionalProjectFile: fileManager.readOptionalProjectFile,
89736
89605
  readProjectFile: fileManager.readProjectFile,
89737
89606
  writeProjectFile: fileManager.writeProjectFile,
89738
- domEditSaveTimestampRef,
89739
89607
  showToast,
89740
89608
  syncHistoryPreviewAfterApply: previewPersistence.syncHistoryPreviewAfterApply,
89741
89609
  waitForPendingDomEditSaves: previewPersistence.waitForPendingDomEditSaves,
@@ -89776,7 +89644,6 @@ function StudioApp() {
89776
89644
  readProjectFile: fileManager.readProjectFile,
89777
89645
  writeProjectFile: fileManager.writeProjectFile,
89778
89646
  updateEditingFileContent: fileManager.updateEditingFileContent,
89779
- domEditSaveTimestampRef,
89780
89647
  editHistory: { recordEdit: editHistory.recordEdit },
89781
89648
  fileTree: fileManager.fileTree,
89782
89649
  importedFontAssetsRef: fileManager.importedFontAssetsRef,
@@ -90023,7 +89890,6 @@ function StudioApp() {
90023
89890
  publishSdkSession: sdkHandle.publish,
90024
89891
  forceReloadSdkSession: sdkHandle.forceReload,
90025
89892
  reloadPreview,
90026
- domEditSaveTimestampRef,
90027
89893
  recordEdit: editHistory.recordEdit,
90028
89894
  onToggleElementHidden: timelineEditing.handleToggleElementHidden,
90029
89895
  onAutoGroupCarveSources: timelineEditing.handleAutoGroupCarveSources,