mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-10 22:20:14 +00:00
fix(studio): gracefully handle visual edits on runtime-generated elements (#1150)
* fix(studio): gracefully handle visual edits on runtime-generated elements When the DOM patcher can't find an element in source HTML (e.g. elements created by JavaScript at runtime like #arrows-svg, .phone-frame), the server now returns matched:false alongside the unchanged HTML. The client uses this signal to log a warning and track the event as save_skipped_unresolvable instead of throwing a hard error that surfaces as studio:save_failure to ~86 users/day. Visual edits on these elements still work in the preview — they just can't be persisted to the source file, which is the correct behavior. * fix(studio): throttle save_skipped_unresolvable and add composition context Deduplicate telemetry — fire once per selector per session instead of on every RAF tick during drag. Add composition path to the event payload for dashboard pivoting.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { useCallback } from "react";
|
||||
import { useCallback, useRef } from "react";
|
||||
import { usePlayerStore } from "../player";
|
||||
import { FONT_EXT } from "../utils/mediaTypes";
|
||||
import type { PatchOperation } from "../utils/sourcePatcher";
|
||||
@@ -128,6 +128,8 @@ export function useDomEditCommits({
|
||||
[fileTree, projectId, importedFontAssetsRef],
|
||||
);
|
||||
|
||||
const reportedUnresolvableRef = useRef(new Set<string>());
|
||||
|
||||
// fallow-ignore-next-line complexity
|
||||
const persistDomEditOperations: PersistDomEditOperations = useCallback(
|
||||
async (selection, operations, options) => {
|
||||
@@ -173,11 +175,28 @@ export function useDomEditCommits({
|
||||
const patchData = (await patchResponse.json()) as {
|
||||
ok?: boolean;
|
||||
changed?: boolean;
|
||||
matched?: boolean;
|
||||
content?: string;
|
||||
};
|
||||
|
||||
if (!patchData.changed) {
|
||||
throw new Error(`Unable to patch ${selection.selector ?? selection.id ?? "selection"}`);
|
||||
if (patchData.matched === false) {
|
||||
const targetKey = selection.selector ?? selection.id ?? "selection";
|
||||
if (!reportedUnresolvableRef.current.has(targetKey)) {
|
||||
reportedUnresolvableRef.current.add(targetKey);
|
||||
trackStudioEvent("save_skipped_unresolvable", {
|
||||
target_id: selection.id ?? undefined,
|
||||
target_selector: selection.selector ?? undefined,
|
||||
target_source_file: selection.sourceFile ?? undefined,
|
||||
composition: activeCompPath ?? undefined,
|
||||
});
|
||||
console.warn(
|
||||
`[studio] Element not found in source: ${targetKey}. ` +
|
||||
"This element may be generated at runtime and cannot be persisted.",
|
||||
);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const patchedContent =
|
||||
|
||||
Reference in New Issue
Block a user