diff --git a/movie_editor/frontend/inspector.js b/movie_editor/frontend/inspector.js index 4903be17..f2f2f5d0 100644 --- a/movie_editor/frontend/inspector.js +++ b/movie_editor/frontend/inspector.js @@ -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 = () => { diff --git a/movie_editor/frontend/player.js b/movie_editor/frontend/player.js index bbe13752..f7fe7ce4 100644 --- a/movie_editor/frontend/player.js +++ b/movie_editor/frontend/player.js @@ -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 ───────────────────────────────────────────────────── diff --git a/movie_editor/frontend/store.js b/movie_editor/frontend/store.js index 0574d48c..dd0d498f 100644 --- a/movie_editor/frontend/store.js +++ b/movie_editor/frontend/store.js @@ -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, }; } diff --git a/movie_editor/frontend/styles.css b/movie_editor/frontend/styles.css index fc6918be..49137b29 100644 --- a/movie_editor/frontend/styles.css +++ b/movie_editor/frontend/styles.css @@ -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); diff --git a/movie_editor/frontend/timeline.js b/movie_editor/frontend/timeline.js index 2a50f37b..421a23c3 100644 --- a/movie_editor/frontend/timeline.js +++ b/movie_editor/frontend/timeline.js @@ -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; }