Clear orphan scene ratings when renders are missing on reload.
Drop stale ratings without playable media, hide rating badges in the UI, and avoid preview 500s when validation fails.
This commit is contained in:
@@ -213,7 +213,9 @@
|
||||
let _globalApplyTimer = null;
|
||||
function scheduleGlobalPromptApply(text) {
|
||||
clearTimeout(_globalApplyTimer);
|
||||
_globalApplyTimer = setTimeout(() => { applyGlobalPromptQuiet(text); }, 500);
|
||||
_globalApplyTimer = setTimeout(() => {
|
||||
applyGlobalPromptQuiet(text).catch((e) => console.warn("Global prompt apply failed:", e));
|
||||
}, 500);
|
||||
}
|
||||
|
||||
function _normalizeSceneText(t) {
|
||||
@@ -500,6 +502,40 @@
|
||||
if (!quiet) notify();
|
||||
}
|
||||
|
||||
function _genUnitHasRender(unitId) {
|
||||
return (state.project?.scenes || []).some(
|
||||
(s) => genUnitId(s) === unitId && !!(state.sceneRenders[s.id]?.media?.filename)
|
||||
);
|
||||
}
|
||||
|
||||
// Ratings apply to a specific render — drop stale ratings when nothing is playable.
|
||||
function _clearOrphanRatings() {
|
||||
if (!state.project) return false;
|
||||
let cleared = false;
|
||||
const seen = new Set();
|
||||
for (const sc of state.project.scenes || []) {
|
||||
if (isVideoClip(sc)) {
|
||||
if (sc.rating) { sc.rating = ""; cleared = true; }
|
||||
continue;
|
||||
}
|
||||
const uid = genUnitId(sc);
|
||||
if (seen.has(uid)) continue;
|
||||
seen.add(uid);
|
||||
const root = genUnitRoot(uid) || sc;
|
||||
if (root.rating && !_genUnitHasRender(uid)) {
|
||||
root.rating = "";
|
||||
cleared = true;
|
||||
}
|
||||
for (const s of state.project.scenes) {
|
||||
if (genUnitId(s) === uid && s.id !== root.id && s.rating) {
|
||||
s.rating = "";
|
||||
cleared = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return cleared;
|
||||
}
|
||||
|
||||
let _validateRendersToken = 0;
|
||||
|
||||
async function _validateSceneRenders() {
|
||||
@@ -507,7 +543,14 @@
|
||||
const token = ++_validateRendersToken;
|
||||
const snapshot = JSON.parse(JSON.stringify(state.sceneRenders || {}));
|
||||
const ids = Object.keys(snapshot);
|
||||
if (!ids.length) return;
|
||||
if (!ids.length) {
|
||||
if (_clearOrphanRatings()) {
|
||||
_syncEditorStateToProject();
|
||||
scheduleSave();
|
||||
notify();
|
||||
}
|
||||
return;
|
||||
}
|
||||
let missing = 0;
|
||||
await Promise.all(ids.map(async (id) => {
|
||||
if (token !== _validateRendersToken) return;
|
||||
@@ -534,8 +577,11 @@
|
||||
}
|
||||
}));
|
||||
if (token !== _validateRendersToken) return;
|
||||
if (missing) {
|
||||
state.notice = `${missing} saved render${missing > 1 ? "s" : ""} no longer on disk — regenerate those clips.`;
|
||||
const clearedRatings = _clearOrphanRatings();
|
||||
if (missing || clearedRatings) {
|
||||
if (missing) {
|
||||
state.notice = `${missing} saved render${missing > 1 ? "s" : ""} no longer on disk — regenerate those clips.`;
|
||||
}
|
||||
_syncEditorStateToProject();
|
||||
scheduleSave();
|
||||
notify();
|
||||
@@ -558,6 +604,10 @@
|
||||
state.gen = { state: "idle", promptId: null, media: [], msg: "" };
|
||||
state.sceneRenders = JSON.parse(JSON.stringify(state.project.scene_renders || {}));
|
||||
state.sceneGhosts = JSON.parse(JSON.stringify(state.project.scene_ghosts || []));
|
||||
if (_clearOrphanRatings()) {
|
||||
_syncEditorStateToProject();
|
||||
scheduleSaveSilent();
|
||||
}
|
||||
_genInFlightIds.clear();
|
||||
_removedDuringGen.clear();
|
||||
if (window.EditorHistory) window.EditorHistory.clear();
|
||||
@@ -995,6 +1045,7 @@
|
||||
source: { type: "video", media_ref: mediaRef },
|
||||
gen_unit_id: root.id,
|
||||
cut_offset_frames: 0,
|
||||
rating: "",
|
||||
});
|
||||
if (state.selectedSceneId && !scene(state.selectedSceneId)) {
|
||||
state.selectedSceneId = root.id;
|
||||
|
||||
@@ -191,7 +191,16 @@
|
||||
});
|
||||
}
|
||||
|
||||
function genUnitHasRender(st, scene) {
|
||||
const uid = S.genUnitId(scene);
|
||||
return (st.project?.scenes || []).some(
|
||||
(s) => S.genUnitId(s) === uid && hasRender(st, s.id)
|
||||
);
|
||||
}
|
||||
|
||||
function sceneRatingRaw(st, scene) {
|
||||
if (S.isVideoClip && S.isVideoClip(scene)) return "";
|
||||
if (!genUnitHasRender(st, scene)) return "";
|
||||
const root = S.genUnitRoot(S.genUnitId(scene)) || scene;
|
||||
return ((root && root.rating) || scene.rating || "").trim();
|
||||
}
|
||||
|
||||
+10
-1
@@ -613,7 +613,16 @@ if web is not None and PromptServer is not None:
|
||||
preview_target = Project.from_dict(p.to_dict())
|
||||
preview_target.scenes = [s for s in preview_target.scenes if not s.excluded]
|
||||
if for_generation:
|
||||
validation = bridge.validate_generation_prompt(p, preview_target)
|
||||
try:
|
||||
validation = bridge.validate_generation_prompt(p, preview_target)
|
||||
except Exception as e: # noqa: BLE001
|
||||
return web.json_response({
|
||||
"combined_prompt": "",
|
||||
"display_prompt": "",
|
||||
"for_generation": True,
|
||||
"parse_error": str(e),
|
||||
"validation_error": str(e),
|
||||
})
|
||||
prompt = validation["generation_prompt"]
|
||||
result = {
|
||||
"combined_prompt": prompt,
|
||||
|
||||
Reference in New Issue
Block a user