Skip to content

Commit 4d647da

Browse files
fix(studio): document SELF_WRITE_SUPPRESS_MS heuristic; fix pre-existing TS errors
Reviewer noted the 2 s suppress window is a footgun. Add a comment explaining the trade-off (short = echo fires anyway; long = masks real edits) and naming the long-term fix (sequence number / content hash on the persist event). Also fix three pre-existing issues in useDomEditCommits.ts on this branch: - PatchOperation was used in UseDomEditCommitsParams but not imported - onTrySdkPersist was called in persistDomEditOperations but missing from both the interface and the function's destructure pattern - onTrySdkPersist missing from useCallback deps (react-hooks/exhaustive-deps) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: Miguel Ángel <miguel07alm@protonmail.com>
1 parent 1e0035b commit 4d647da

2 files changed

Lines changed: 16 additions & 0 deletions

File tree

packages/studio/src/hooks/useDomEditCommits.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { buildDomEditPatchTarget, type DomEditSelection } from "../components/ed
99
import { fontFamilyFromAssetPath, type ImportedFontAsset } from "../components/editor/fontAssets";
1010
import type { EditHistoryKind } from "../utils/editHistory";
1111
import type { PersistDomEditOperations } from "./domEditCommitTypes";
12+
import type { PatchOperation } from "../utils/sourcePatcher";
1213
import { useDomEditPositionPatchCommit } from "./useDomEditPositionPatchCommit";
1314
import { useDomEditTextCommits } from "./useDomEditTextCommits";
1415
import { useDomGeometryCommits } from "./useDomGeometryCommits";
@@ -77,6 +78,13 @@ export interface UseDomEditCommitsParams {
7778
) => Promise<DomEditSelection | null>;
7879
/** Stage 7 Step 3b: called after a successful server-side element patch. */
7980
onDomEditPersisted?: (selection: DomEditSelection, operations: PatchOperation[]) => void;
81+
/** Stage 7 Step 3c: called before the server-side patch path; returns true if SDK handled it. */
82+
onTrySdkPersist?: (
83+
selection: DomEditSelection,
84+
operations: PatchOperation[],
85+
originalContent: string,
86+
targetPath: string,
87+
) => Promise<boolean>;
8088
}
8189

8290
export function useDomEditCommits({
@@ -98,6 +106,7 @@ export function useDomEditCommits({
98106
refreshDomEditSelectionFromPreview,
99107
buildDomSelectionFromTarget,
100108
onDomEditPersisted,
109+
onTrySdkPersist,
101110
}: UseDomEditCommitsParams) {
102111
const resolveImportedFontAsset = useCallback(
103112
(fontFamilyValue: string): ImportedFontAsset | null => {
@@ -237,6 +246,7 @@ export function useDomEditCommits({
237246
reloadPreview,
238247
showToast,
239248
onDomEditPersisted,
249+
onTrySdkPersist,
240250
],
241251
);
242252

packages/studio/src/hooks/useSdkSession.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@ export function shouldReloadSdkSession(payload: unknown, activeCompPath: string
2828
* is therefore purely additive — no SDK self-write exists yet, so there is no
2929
* persist echo. Step 3c must add self-write suppression once dispatch writes.
3030
*/
31+
// Time-window heuristic: suppress file-change reloads for 2 s after our own
32+
// SDK cutover write, to avoid an echo-reload on the write we just committed.
33+
// Footgun: if 2 s is too short (slow FS / network) the reload fires anyway;
34+
// if too long it masks a legitimate external edit. The long-term shape is a
35+
// sequence number or content hash threaded through the persist event so the
36+
// comparison is exact rather than time-based.
3137
const SELF_WRITE_SUPPRESS_MS = 2000;
3238

3339
export function useSdkSession(

0 commit comments

Comments
 (0)