fix(editor): dismissing pipeline setup could be undone by an in-flight reopen
chooseFamily reopens the modal after three round-trips, so a close during that window was reverted. User closes now supersede pending continuations.
This commit is contained in:
@@ -86,6 +86,14 @@
|
||||
looked exactly like one where the feature was switched off.
|
||||
|
||||
### Fixed
|
||||
- **"No, I'll use my own pipeline" left the setup modal on screen.** Picking a model family
|
||||
starts a chain of requests that reopens the modal with fresh prerequisites; dismissing it
|
||||
mid-flight closed it, then the reply landed and put it straight back — and since opting out
|
||||
installs nothing, the prerequisites were still missing, so it always reopened. Closes the
|
||||
user asks for now supersede anything in flight. The choice is also recorded before the
|
||||
save round-trip rather than after it, and a save that fails says so instead of leaving the
|
||||
project quietly still on the built-in pipeline.
|
||||
|
||||
- **An output can be wired to several destinations while adding a node**, not only after.
|
||||
The Add-node panel offered one destination per output and told you to finish the job on
|
||||
the node's page; it now uses the same multi-destination editor the node page does, with
|
||||
|
||||
@@ -20,12 +20,27 @@
|
||||
try { localStorage.setItem(LS_KEY, "1"); } catch (_) {}
|
||||
}
|
||||
|
||||
// Bumped by every close the USER asked for. chooseFamily / applyFamily / useOwnPipeline
|
||||
// each span two or three round-trips and then reopen the modal with fresh deps; without
|
||||
// this, a continuation that started before the user dismissed the modal reopens it
|
||||
// afterwards — which is exactly what "No, I'll use my own pipeline" looked like, since
|
||||
// disabling the built-in pipeline installs nothing, so `needs_setup` is still true when
|
||||
// the in-flight chooseFamily lands.
|
||||
let _closeToken = 0;
|
||||
|
||||
function closeModal() {
|
||||
if (_pollTimer) { clearTimeout(_pollTimer); _pollTimer = null; }
|
||||
overlay?.remove();
|
||||
overlay = null;
|
||||
}
|
||||
|
||||
// Close AND supersede anything already in flight. Use this for every close the user
|
||||
// initiates; closeModal() alone is for internal teardown before a reopen.
|
||||
function dismissModal() {
|
||||
_closeToken += 1;
|
||||
closeModal();
|
||||
}
|
||||
|
||||
function builtInPipelineActive(st) {
|
||||
const m = st.models || {};
|
||||
return !m.disable_core;
|
||||
@@ -43,13 +58,29 @@
|
||||
}
|
||||
|
||||
async function useOwnPipeline() {
|
||||
if (!S.get().project) return;
|
||||
const models = JSON.parse(JSON.stringify(S.get().models || S.get().project?.models || { slots: [] }));
|
||||
models.disable_core = true;
|
||||
await API.saveModels(S.get().project.id, models);
|
||||
await refreshModels(models);
|
||||
const proj = S.get().project;
|
||||
if (!proj) {
|
||||
// Nothing to write the choice to. Still close: leaving the modal up with a button
|
||||
// that does nothing when pressed is the worse of the two failures.
|
||||
dismissModal();
|
||||
return;
|
||||
}
|
||||
// Dismissed BEFORE the awaits: the decision is already made, and holding the modal open
|
||||
// for two round-trips is what let an in-flight family lookup reopen it afterwards.
|
||||
setDismissed();
|
||||
closeModal();
|
||||
dismissModal();
|
||||
const models = JSON.parse(JSON.stringify(S.get().models || proj.models || { slots: [] }));
|
||||
models.disable_core = true;
|
||||
try {
|
||||
await API.saveModels(proj.id, models);
|
||||
} catch (e) {
|
||||
// The choice did NOT persist — saying so beats a project that quietly still runs the
|
||||
// built-in pipeline on the next Generate.
|
||||
alert("Could not save the pipeline choice: " + (e?.message || e)
|
||||
+ "\n\nSet it in Models → Enable built-in pipeline.");
|
||||
return;
|
||||
}
|
||||
await refreshModels(models);
|
||||
}
|
||||
|
||||
function packList(deps) {
|
||||
@@ -236,9 +267,12 @@
|
||||
|
||||
async function chooseFamily(key) {
|
||||
if (!S.get().project) return;
|
||||
const tok = _closeToken;
|
||||
await applyFamily(key);
|
||||
if (tok !== _closeToken) return; // user closed the modal while this was in flight
|
||||
let deps;
|
||||
try { deps = await API.pipelineDeps(S.get().project?.id); } catch (_) { closeModal(); return; }
|
||||
if (tok !== _closeToken) return;
|
||||
if (!deps?.needs_setup) { closeModal(); return; }
|
||||
openModal(deps);
|
||||
}
|
||||
@@ -382,12 +416,12 @@
|
||||
foot.append(ownBtn);
|
||||
const dismissBtn = el("button", "btn ghost", "Close");
|
||||
dismissBtn.type = "button";
|
||||
dismissBtn.onclick = () => closeModal();
|
||||
dismissBtn.onclick = () => dismissModal();
|
||||
foot.append(dismissBtn);
|
||||
modal.append(foot);
|
||||
|
||||
overlay.append(modal);
|
||||
overlay.addEventListener("click", (e) => { if (e.target === overlay) closeModal(); });
|
||||
overlay.addEventListener("click", (e) => { if (e.target === overlay) dismissModal(); });
|
||||
document.body.append(overlay);
|
||||
}
|
||||
|
||||
@@ -395,7 +429,7 @@
|
||||
// not open behind it — or, worse, on top of the editor the moment the wizard finishes.
|
||||
function markHandled() {
|
||||
setDismissed();
|
||||
closeModal();
|
||||
dismissModal();
|
||||
}
|
||||
|
||||
async function maybePrompt() {
|
||||
@@ -404,8 +438,10 @@
|
||||
if (dismissed()) return;
|
||||
const st = S.get();
|
||||
if (!st.project || !builtInPipelineActive(st)) return;
|
||||
const tok = _closeToken;
|
||||
let deps;
|
||||
try { deps = await API.pipelineDeps(S.get().project?.id); } catch (_) { return; }
|
||||
if (tok !== _closeToken) return;
|
||||
if (!deps?.needs_setup) return;
|
||||
openModal(deps);
|
||||
}
|
||||
@@ -414,8 +450,10 @@
|
||||
// after it has been dismissed once (the auto-prompt is one-shot per browser).
|
||||
async function open() {
|
||||
if (!S.get().project) return;
|
||||
const tok = _closeToken;
|
||||
let deps;
|
||||
try { deps = await API.pipelineDeps(S.get().project?.id); } catch (_) { return; }
|
||||
if (tok !== _closeToken) return;
|
||||
openModal(deps);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user