Only show i2v stale warning on clip after anchor actually changes.
Require sourceSnapshotted on render metadata so refresh does not false-positive. Remove duplicate anchor hints from toolbar, player, and inspector; keep a single on-clip notice without a (none) label. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
co-authored by
Cursor
parent
1fa74696a0
commit
379ae77f87
@@ -171,14 +171,6 @@
|
||||
warn.append(el("div", "render-prompt-text", promptMismatch.rendered || "(empty)"));
|
||||
body.append(warn);
|
||||
}
|
||||
const anchorMismatch = S.renderAnchorMismatch ? S.renderAnchorMismatch(scene.id) : null;
|
||||
if (anchorMismatch) {
|
||||
const warn = el("div", "render-prompt-warn render-anchor-warn");
|
||||
warn.append(el("div", "render-prompt-warn-title", "i2v image changed · showing previous generation"));
|
||||
warn.append(el("div", "render-prompt-text", anchorMismatch.renderedLabel || "(none)"));
|
||||
body.append(warn);
|
||||
}
|
||||
|
||||
const src = el("select");
|
||||
SRC.forEach(([v, label]) => { const o = el("option", null, label); o.value = v; if ((root.source?.type) === v) o.selected = true; src.append(o); });
|
||||
src.onchange = () => {
|
||||
|
||||
@@ -119,29 +119,15 @@
|
||||
}
|
||||
function _showRenderPrompt(sceneId) {
|
||||
if (!_promptEl) return;
|
||||
const promptMismatch = sceneId && S.renderPromptMismatch ? S.renderPromptMismatch(sceneId) : null;
|
||||
const anchorMismatch = sceneId && S.renderAnchorMismatch ? S.renderAnchorMismatch(sceneId) : null;
|
||||
if (!promptMismatch && !anchorMismatch) {
|
||||
const mismatch = sceneId && S.renderPromptMismatch ? S.renderPromptMismatch(sceneId) : null;
|
||||
if (!mismatch) {
|
||||
_promptEl.style.display = "none";
|
||||
_promptEl.textContent = "";
|
||||
_promptEl.classList.remove("anchor-stale");
|
||||
return;
|
||||
}
|
||||
_promptEl.style.display = "";
|
||||
if (anchorMismatch && !promptMismatch) {
|
||||
_promptEl.classList.add("anchor-stale");
|
||||
_promptEl.title = `Generated with i2v image: ${anchorMismatch.renderedLabel}`;
|
||||
_promptEl.textContent = "i2v image changed · showing previous generation";
|
||||
} else {
|
||||
_promptEl.classList.remove("anchor-stale");
|
||||
if (anchorMismatch && promptMismatch) {
|
||||
_promptEl.title = `i2v: ${anchorMismatch.renderedLabel} · prompt: ${promptMismatch.rendered}`;
|
||||
_promptEl.textContent = `i2v image changed · generated with: ${promptMismatch.rendered}`;
|
||||
} else {
|
||||
_promptEl.title = "Timeline prompt was edited after generation - rate against this text";
|
||||
_promptEl.textContent = `Generated with: ${promptMismatch.rendered}`;
|
||||
}
|
||||
}
|
||||
_promptEl.title = "Timeline prompt was edited after generation - rate against this text";
|
||||
_promptEl.textContent = `Generated with: ${mismatch.rendered}`;
|
||||
}
|
||||
|
||||
// ── video pool management ─────────────────────────────────────────────────────
|
||||
|
||||
@@ -355,6 +355,7 @@
|
||||
anchor: rp.anchor ?? anchor,
|
||||
sourceType: rp.sourceType ?? sourceType,
|
||||
mediaRef: rp.mediaRef !== undefined ? rp.mediaRef : mediaRef,
|
||||
sourceSnapshotted: true,
|
||||
};
|
||||
});
|
||||
}
|
||||
@@ -1089,6 +1090,7 @@
|
||||
anchor: (state.project?.anchor || "").trim(),
|
||||
sourceType: src.type || "carry",
|
||||
mediaRef: src.media_ref || null,
|
||||
sourceSnapshotted: true,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1121,7 +1123,7 @@
|
||||
|
||||
function renderAnchorMismatch(sceneId) {
|
||||
const snap = renderPromptForScene(sceneId);
|
||||
if (!snap) return null;
|
||||
if (!snap?.sourceSnapshotted) return null;
|
||||
const current = _snapshotRenderSource(sceneId);
|
||||
if (!current) return null;
|
||||
const renderedType = snap.sourceType || "carry";
|
||||
@@ -1130,10 +1132,10 @@
|
||||
return {
|
||||
renderedType,
|
||||
renderedRef,
|
||||
renderedLabel: renderMediaLabel(renderedRef),
|
||||
renderedLabel: renderedRef ? renderMediaLabel(renderedRef) : null,
|
||||
currentType: current.sourceType,
|
||||
currentRef: current.mediaRef,
|
||||
currentLabel: renderMediaLabel(current.mediaRef),
|
||||
currentLabel: current.mediaRef ? renderMediaLabel(current.mediaRef) : null,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -674,11 +674,7 @@ body.tl-reordering { cursor: grabbing; user-select: none; }
|
||||
.clip.prompt-mismatch { border-color: color-mix(in srgb, var(--amber) 45%, var(--line)); }
|
||||
.clip.anchor-mismatch { border-color: color-mix(in srgb, var(--teal-soft) 42%, var(--line)); }
|
||||
.clip.stale-render.rendered::after { color: var(--amber-2); text-shadow: 0 0 5px rgba(224, 162, 58, .7); }
|
||||
.clip-gen-anchor .clip-gen-prompt-label { color: var(--teal-soft); }
|
||||
.clip-gen-anchor .clip-gen-prompt-text { color: #c8fff4; }
|
||||
.tl-render-anchor { color: #c8fff4; border-color: color-mix(in srgb, var(--teal-soft) 40%, var(--line)); }
|
||||
.render-anchor-warn { border-color: color-mix(in srgb, var(--teal-soft) 35%, var(--line)); }
|
||||
.render-anchor-warn .render-prompt-warn-title { color: var(--teal-soft); }
|
||||
.clip-actions { position: absolute; top: 5px; right: 8px; display: flex; gap: 2px; opacity: 0; transition: opacity .12s; }
|
||||
.clip:hover .clip-actions { opacity: 1; }
|
||||
.ic-btn { width: 18px; height: 18px; padding: 0; font-size: 11px; line-height: 1; border: 1px solid var(--line);
|
||||
|
||||
@@ -445,9 +445,11 @@
|
||||
if (anchorMismatch) {
|
||||
clip.classList.add("anchor-mismatch");
|
||||
const gen = el("div", "clip-gen-prompt clip-gen-anchor");
|
||||
gen.title = "i2v anchor changed after generation - preview shows the previous render";
|
||||
gen.title = anchorMismatch.renderedLabel
|
||||
? `Generated with i2v image: ${anchorMismatch.renderedLabel}`
|
||||
: "i2v anchor changed after generation - preview shows the previous render";
|
||||
gen.append(el("span", "clip-gen-prompt-label", "i2v image changed"));
|
||||
gen.append(el("span", "clip-gen-prompt-text", `Showing previous generation (${anchorMismatch.renderedLabel})`));
|
||||
gen.append(el("span", "clip-gen-prompt-text", "Showing previous generation"));
|
||||
clip.append(gen);
|
||||
}
|
||||
if (S.renderPromptMismatch) {
|
||||
@@ -836,15 +838,9 @@
|
||||
const sc = S.scene(st.selectedSceneId);
|
||||
if (!sc) return wrap;
|
||||
const sceneNo = p.scenes.indexOf(sc) + 1;
|
||||
const promptMismatch = S.renderPromptMismatch ? S.renderPromptMismatch(sc.id) : null;
|
||||
const anchorMismatch = S.renderAnchorMismatch ? S.renderAnchorMismatch(sc.id) : null;
|
||||
const rlabel = el("span", "tl-keys", `★ Scene ${sceneNo}`);
|
||||
const rsel = el("select", "tl-rating");
|
||||
rsel.title = anchorMismatch
|
||||
? "i2v image changed - rate the previous generation shown in preview"
|
||||
: promptMismatch
|
||||
? "Rate against the generated prompt - timeline text was edited after this render"
|
||||
: "Rate this scene's render - FunPack Studio refines from it on next generation";
|
||||
rsel.title = "Rate this scene's render - FunPack Studio refines from it on next generation";
|
||||
rsel.append(new Option("- rate -", ""));
|
||||
(st.ratingLabels || []).forEach((l) => {
|
||||
const o = new Option(l, l);
|
||||
@@ -854,15 +850,6 @@
|
||||
rsel.onchange = () => S.setSceneRating(sc.id, rsel.value);
|
||||
wrap.append(rlabel);
|
||||
wrap.append(rsel);
|
||||
if (anchorMismatch) {
|
||||
const hint = el("span", "tl-render-prompt tl-render-anchor", "i2v image changed · showing previous generation");
|
||||
hint.title = `Generated with ${anchorMismatch.renderedLabel}`;
|
||||
wrap.append(hint);
|
||||
} else if (promptMismatch) {
|
||||
const hint = el("span", "tl-render-prompt", promptMismatch.rendered);
|
||||
hint.title = "Generated with this prompt - use it when rating (timeline text differs)";
|
||||
wrap.append(hint);
|
||||
}
|
||||
return wrap;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user