fix: Reactive focus modal ignores outside clicks; only x / Cancel / a step ends it
This commit is contained in:
@@ -79,7 +79,7 @@
|
||||
return sel;
|
||||
}
|
||||
|
||||
function openModal({ title, subtitle, widthClass, onClose }) {
|
||||
function openModal({ title, subtitle, widthClass, onClose, sticky }) {
|
||||
const overlay = document.createElement("div");
|
||||
overlay.className = "modal-overlay ov-modal-overlay";
|
||||
const box = document.createElement("div");
|
||||
@@ -115,7 +115,7 @@
|
||||
if (onClose) onClose();
|
||||
};
|
||||
closeBtn.onclick = close;
|
||||
overlay.addEventListener("click", (e) => { if (e.target === overlay) close(); });
|
||||
if (!sticky) overlay.addEventListener("click", (e) => { if (e.target === overlay) close(); });
|
||||
document.body.append(overlay);
|
||||
return { overlay, body, foot, close };
|
||||
}
|
||||
|
||||
@@ -103,6 +103,7 @@
|
||||
title: "Reactive focus",
|
||||
subtitle: "",
|
||||
widthClass: "ov-modal-wide",
|
||||
sticky: true, // a stray click must not cancel the run; only × / Cancel / a step does
|
||||
onClose: () => { if (!done) { done = true; resolve(null); } },
|
||||
});
|
||||
const show = () => {
|
||||
@@ -138,9 +139,10 @@
|
||||
const wantMoves = !!(rf.camera_moves && rf.reactive_focus && chance(rf.camera_moves_chance, 0.7) > 0);
|
||||
const wantViews = !!(rf.shot_views && rf.reactive_focus && chance(rf.shot_view_chance, 0.4) > 0);
|
||||
if (!wantMoves && !wantViews) return true;
|
||||
let scenes;
|
||||
let scenes, seen = {};
|
||||
try {
|
||||
scenes = (await window.MovieEditorAPI.focusOptions(project.id, sceneIds)).scenes || [];
|
||||
seen = await window.MovieEditorAPI.focusOptions(project.id, sceneIds);
|
||||
scenes = seen.scenes || [];
|
||||
} catch (e) {
|
||||
console.warn("[FunPack] reactive focus: could not list targets —", e.message);
|
||||
window.Store.get().notice = `Reactive focus was skipped: ${e.message}`;
|
||||
@@ -157,7 +159,15 @@
|
||||
const todo = pending(scenes, savedViews, "views", (s) => !s.already && s.candidates.length);
|
||||
if (todo.length) steps.push({ kind: "views", title: "Views", page: viewsPage(todo) });
|
||||
}
|
||||
if (!steps.length) return true;
|
||||
if (!steps.length) {
|
||||
// Say why nothing was asked, or "no modal" is indistinguishable from "broken".
|
||||
const why = !seen.with_shot_marks
|
||||
? `no [Shot N] found in the ${seen.texts == null ? "" : seen.texts + " "}scene text(s) sent to generation`
|
||||
: scenes.length ? "every shot is already decided or already has a camera move/view"
|
||||
: "no shot has a target or view to offer";
|
||||
window.Store.get().notice = `Reactive focus: nothing to ask — ${why}.`;
|
||||
return true;
|
||||
}
|
||||
const res = await ask(steps);
|
||||
if (!res) return false;
|
||||
const patch = {}, learn = { decisions: [], views: [] };
|
||||
|
||||
@@ -3129,13 +3129,14 @@ if web is not None and PromptServer is not None:
|
||||
if shots or views:
|
||||
out.append({"index": i, "preview": " ".join(text.split())[:80],
|
||||
"shots": shots, "views": views})
|
||||
return out
|
||||
marked = sum(1 for t in texts if "[shot" in t.lower())
|
||||
return out, {"texts": len(texts), "with_shot_marks": marked}
|
||||
|
||||
try:
|
||||
scenes = await asyncio.to_thread(_build)
|
||||
scenes, seen = await asyncio.to_thread(_build)
|
||||
except Exception as e: # noqa: BLE001
|
||||
return web.json_response({"detail": f"Could not list camera targets: {e}"}, status=500)
|
||||
return web.json_response({"scenes": scenes})
|
||||
return web.json_response({"scenes": scenes, **seen})
|
||||
|
||||
@routes.post(UI_PREFIX + "/api/focus/learn")
|
||||
async def _focus_learn(req):
|
||||
|
||||
Reference in New Issue
Block a user