Spaces:
Running on Zero
Running on Zero
fix: lock session controls during turns
Browse filesCo-authored-by: Codex <noreply@openai.com>
- static/app.js +23 -0
- static/styles.css +11 -0
static/app.js
CHANGED
|
@@ -38,6 +38,7 @@ let turnWatchdog = null;
|
|
| 38 |
let sawTurnToken = false;
|
| 39 |
let bootstrapData = null;
|
| 40 |
let sessionRevision = 0;
|
|
|
|
| 41 |
|
| 42 |
bootstrap().catch(handleBootstrapError);
|
| 43 |
|
|
@@ -108,6 +109,7 @@ async function runTurn(message) {
|
|
| 108 |
input.value = "";
|
| 109 |
submit.disabled = true;
|
| 110 |
setCommandDisabled(true);
|
|
|
|
| 111 |
ink.classList.remove("bleed", "gold");
|
| 112 |
corrections.textContent = "";
|
| 113 |
planEl.innerHTML = "";
|
|
@@ -137,6 +139,7 @@ async function runTurn(message) {
|
|
| 137 |
clearTurnWatchdog();
|
| 138 |
submit.disabled = false;
|
| 139 |
setCommandDisabled(false);
|
|
|
|
| 140 |
input.focus();
|
| 141 |
}
|
| 142 |
}
|
|
@@ -167,6 +170,7 @@ function handleBootstrapError(error) {
|
|
| 167 |
submit.disabled = true;
|
| 168 |
input.disabled = true;
|
| 169 |
setCommandDisabled(true);
|
|
|
|
| 170 |
ink.textContent = `The project index could not be opened: ${error.message}`;
|
| 171 |
ink.classList.remove("thinking", "gold");
|
| 172 |
ink.classList.add("bleed");
|
|
@@ -206,6 +210,19 @@ function restoreExportButtonLabels() {
|
|
| 206 |
exportButton.textContent = PNG_EXPORT_LABEL;
|
| 207 |
}
|
| 208 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 209 |
function resetSession() {
|
| 210 |
if (!bootstrapData) return;
|
| 211 |
bumpSessionRevision();
|
|
@@ -215,6 +232,7 @@ function resetSession() {
|
|
| 215 |
currentArtifact = null;
|
| 216 |
submit.disabled = false;
|
| 217 |
input.disabled = false;
|
|
|
|
| 218 |
input.value = "";
|
| 219 |
ink.textContent = "The book is open. The next page waits for its first line.";
|
| 220 |
ink.classList.remove("thinking", "bleed", "gold");
|
|
@@ -241,6 +259,7 @@ async function loadDemoSession() {
|
|
| 241 |
bumpSessionRevision();
|
| 242 |
submit.disabled = true;
|
| 243 |
setCommandDisabled(true);
|
|
|
|
| 244 |
ink.classList.remove("bleed", "gold");
|
| 245 |
ink.classList.add("thinking");
|
| 246 |
ink.textContent = "A sample page is being inked.";
|
|
@@ -256,6 +275,7 @@ async function loadDemoSession() {
|
|
| 256 |
} finally {
|
| 257 |
submit.disabled = false;
|
| 258 |
setCommandDisabled(false);
|
|
|
|
| 259 |
input.focus();
|
| 260 |
}
|
| 261 |
}
|
|
@@ -418,6 +438,7 @@ function renderTargets(selectedTargets) {
|
|
| 418 |
type="checkbox"
|
| 419 |
data-target="${escapeAttribute(option)}"
|
| 420 |
aria-label="${escapeAttribute(profile.label)}"
|
|
|
|
| 421 |
${selected.has(option) ? "checked" : ""}
|
| 422 |
/>
|
| 423 |
<span class="target-copy">
|
|
@@ -444,6 +465,7 @@ function renderProfile(profile) {
|
|
| 444 |
data-profile-field="${escapeAttribute(field)}"
|
| 445 |
value="${escapeAttribute(profile?.[field] || "")}"
|
| 446 |
autocomplete="off"
|
|
|
|
| 447 |
/>
|
| 448 |
`;
|
| 449 |
profileEl.append(row);
|
|
@@ -518,6 +540,7 @@ function renderIdeas(ideas) {
|
|
| 518 |
const item = document.createElement("button");
|
| 519 |
item.type = "button";
|
| 520 |
item.className = `idea ${selected ? "current" : ""}`;
|
|
|
|
| 521 |
item.dataset.ideaId = idea.id || "";
|
| 522 |
item.setAttribute("aria-pressed", selected ? "true" : "false");
|
| 523 |
item.innerHTML = `
|
|
|
|
| 38 |
let sawTurnToken = false;
|
| 39 |
let bootstrapData = null;
|
| 40 |
let sessionRevision = 0;
|
| 41 |
+
let sessionControlsLocked = false;
|
| 42 |
|
| 43 |
bootstrap().catch(handleBootstrapError);
|
| 44 |
|
|
|
|
| 109 |
input.value = "";
|
| 110 |
submit.disabled = true;
|
| 111 |
setCommandDisabled(true);
|
| 112 |
+
setSessionControlsDisabled(true);
|
| 113 |
ink.classList.remove("bleed", "gold");
|
| 114 |
corrections.textContent = "";
|
| 115 |
planEl.innerHTML = "";
|
|
|
|
| 139 |
clearTurnWatchdog();
|
| 140 |
submit.disabled = false;
|
| 141 |
setCommandDisabled(false);
|
| 142 |
+
setSessionControlsDisabled(false);
|
| 143 |
input.focus();
|
| 144 |
}
|
| 145 |
}
|
|
|
|
| 170 |
submit.disabled = true;
|
| 171 |
input.disabled = true;
|
| 172 |
setCommandDisabled(true);
|
| 173 |
+
setSessionControlsDisabled(true);
|
| 174 |
ink.textContent = `The project index could not be opened: ${error.message}`;
|
| 175 |
ink.classList.remove("thinking", "gold");
|
| 176 |
ink.classList.add("bleed");
|
|
|
|
| 210 |
exportButton.textContent = PNG_EXPORT_LABEL;
|
| 211 |
}
|
| 212 |
|
| 213 |
+
function setSessionControlsDisabled(disabled) {
|
| 214 |
+
sessionControlsLocked = disabled;
|
| 215 |
+
targetsEl.querySelectorAll("input[data-target]").forEach((target) => {
|
| 216 |
+
target.disabled = disabled;
|
| 217 |
+
});
|
| 218 |
+
profileEl.querySelectorAll("input[data-profile-field]").forEach((field) => {
|
| 219 |
+
field.disabled = disabled;
|
| 220 |
+
});
|
| 221 |
+
ideasEl.querySelectorAll("button[data-idea-id]").forEach((idea) => {
|
| 222 |
+
idea.disabled = disabled;
|
| 223 |
+
});
|
| 224 |
+
}
|
| 225 |
+
|
| 226 |
function resetSession() {
|
| 227 |
if (!bootstrapData) return;
|
| 228 |
bumpSessionRevision();
|
|
|
|
| 232 |
currentArtifact = null;
|
| 233 |
submit.disabled = false;
|
| 234 |
input.disabled = false;
|
| 235 |
+
setSessionControlsDisabled(false);
|
| 236 |
input.value = "";
|
| 237 |
ink.textContent = "The book is open. The next page waits for its first line.";
|
| 238 |
ink.classList.remove("thinking", "bleed", "gold");
|
|
|
|
| 259 |
bumpSessionRevision();
|
| 260 |
submit.disabled = true;
|
| 261 |
setCommandDisabled(true);
|
| 262 |
+
setSessionControlsDisabled(true);
|
| 263 |
ink.classList.remove("bleed", "gold");
|
| 264 |
ink.classList.add("thinking");
|
| 265 |
ink.textContent = "A sample page is being inked.";
|
|
|
|
| 275 |
} finally {
|
| 276 |
submit.disabled = false;
|
| 277 |
setCommandDisabled(false);
|
| 278 |
+
setSessionControlsDisabled(false);
|
| 279 |
input.focus();
|
| 280 |
}
|
| 281 |
}
|
|
|
|
| 438 |
type="checkbox"
|
| 439 |
data-target="${escapeAttribute(option)}"
|
| 440 |
aria-label="${escapeAttribute(profile.label)}"
|
| 441 |
+
${sessionControlsLocked ? "disabled" : ""}
|
| 442 |
${selected.has(option) ? "checked" : ""}
|
| 443 |
/>
|
| 444 |
<span class="target-copy">
|
|
|
|
| 465 |
data-profile-field="${escapeAttribute(field)}"
|
| 466 |
value="${escapeAttribute(profile?.[field] || "")}"
|
| 467 |
autocomplete="off"
|
| 468 |
+
${sessionControlsLocked ? "disabled" : ""}
|
| 469 |
/>
|
| 470 |
`;
|
| 471 |
profileEl.append(row);
|
|
|
|
| 540 |
const item = document.createElement("button");
|
| 541 |
item.type = "button";
|
| 542 |
item.className = `idea ${selected ? "current" : ""}`;
|
| 543 |
+
item.disabled = sessionControlsLocked;
|
| 544 |
item.dataset.ideaId = idea.id || "";
|
| 545 |
item.setAttribute("aria-pressed", selected ? "true" : "false");
|
| 546 |
item.innerHTML = `
|
static/styles.css
CHANGED
|
@@ -334,6 +334,17 @@ button:disabled {
|
|
| 334 |
background: rgba(255, 241, 196, 0.56);
|
| 335 |
}
|
| 336 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 337 |
.idea:focus-visible {
|
| 338 |
outline: 2px solid rgba(47, 122, 73, 0.5);
|
| 339 |
outline-offset: 2px;
|
|
|
|
| 334 |
background: rgba(255, 241, 196, 0.56);
|
| 335 |
}
|
| 336 |
|
| 337 |
+
.idea:disabled,
|
| 338 |
+
.target-toggle:has(input:disabled),
|
| 339 |
+
.profile-field:has(input:disabled) {
|
| 340 |
+
opacity: 0.64;
|
| 341 |
+
cursor: wait;
|
| 342 |
+
}
|
| 343 |
+
|
| 344 |
+
.idea:disabled {
|
| 345 |
+
cursor: wait;
|
| 346 |
+
}
|
| 347 |
+
|
| 348 |
.idea:focus-visible {
|
| 349 |
outline: 2px solid rgba(47, 122, 73, 0.5);
|
| 350 |
outline-offset: 2px;
|