JacobLinCool Codex commited on
Commit
41e12b2
·
verified ·
1 Parent(s): be083b8

fix: ignore stale export completions

Browse files

Co-authored-by: Codex <noreply@openai.com>

Files changed (1) hide show
  1. static/app.js +28 -1
static/app.js CHANGED
@@ -37,6 +37,7 @@ let profileFields = [];
37
  let turnWatchdog = null;
38
  let sawTurnToken = false;
39
  let bootstrapData = null;
 
40
 
41
  bootstrap().catch(handleBootstrapError);
42
 
@@ -103,6 +104,7 @@ ideasEl.addEventListener("click", (event) => {
103
  });
104
 
105
  async function runTurn(message) {
 
106
  input.value = "";
107
  submit.disabled = true;
108
  setCommandDisabled(true);
@@ -189,12 +191,30 @@ function defaultSession(data = bootstrapData) {
189
  };
190
  }
191
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
192
  function resetSession() {
193
  if (!bootstrapData) return;
 
194
  clearTurnWatchdog();
195
  clearSavedSession();
196
  session = defaultSession(bootstrapData);
197
  currentArtifact = null;
 
 
198
  input.value = "";
199
  ink.textContent = "The book is open. The next page waits for its first line.";
200
  ink.classList.remove("thinking", "bleed", "gold");
@@ -209,6 +229,7 @@ function resetSession() {
209
  renderPlan([]);
210
  renderProjects(bootstrapData.top_projects || []);
211
  renderWhitespace(bootstrapData.whitespace || []);
 
212
  exportButton.disabled = true;
213
  setButtonDisabled(exportNotesButton, true);
214
  setButtonDisabled(exportChapterButton, true);
@@ -217,6 +238,7 @@ function resetSession() {
217
  }
218
 
219
  async function loadDemoSession() {
 
220
  submit.disabled = true;
221
  setCommandDisabled(true);
222
  ink.classList.remove("bleed", "gold");
@@ -524,6 +546,7 @@ function selectIdea(ideaId) {
524
  if (!ideaId || !Array.isArray(session.ideas)) return;
525
  const idea = session.ideas.find((item) => item.id === ideaId);
526
  if (!idea) return;
 
527
  session.current_idea_id = idea.id;
528
  if (Array.isArray(idea.targets) && idea.targets.length) {
529
  session.targets = targetOptions.filter((option) => idea.targets.includes(option));
@@ -757,6 +780,7 @@ async function exportChapter() {
757
 
758
  async function exportMarkdown({ endpoint, filename, button, busyLabel, pendingLabel, successLabel }) {
759
  if (!button || button.disabled) return;
 
760
  const idleLabel = button.textContent;
761
  button.disabled = true;
762
  button.textContent = busyLabel;
@@ -771,15 +795,18 @@ async function exportMarkdown({ endpoint, filename, button, busyLabel, pendingLa
771
  const data = Array.isArray(result.data) ? result.data[0] : result.data;
772
  const text = String(data || "");
773
  if (!text.trim()) throw new Error("empty export");
 
774
  downloadText(filename, text, "text/markdown;charset=utf-8");
775
  session.ui_status = `${successLabel}: ${filename}`;
776
  corrections.textContent = session.ui_status;
777
  } catch (error) {
 
778
  session.ui_status = `Export failed: ${error.message}`;
779
  corrections.textContent = session.ui_status;
780
  } finally {
781
- saveSession();
782
  button.textContent = idleLabel;
 
 
783
  setCommandDisabled(false);
784
  }
785
  }
 
37
  let turnWatchdog = null;
38
  let sawTurnToken = false;
39
  let bootstrapData = null;
40
+ let sessionRevision = 0;
41
 
42
  bootstrap().catch(handleBootstrapError);
43
 
 
104
  });
105
 
106
  async function runTurn(message) {
107
+ bumpSessionRevision();
108
  input.value = "";
109
  submit.disabled = true;
110
  setCommandDisabled(true);
 
191
  };
192
  }
193
 
194
+ function bumpSessionRevision() {
195
+ sessionRevision += 1;
196
+ return sessionRevision;
197
+ }
198
+
199
+ function isCurrentSessionRevision(revision) {
200
+ return revision === sessionRevision;
201
+ }
202
+
203
+ function restoreExportButtonLabels() {
204
+ exportNotesButton.textContent = "Notes";
205
+ exportChapterButton.textContent = "Chapter";
206
+ exportButton.textContent = PNG_EXPORT_LABEL;
207
+ }
208
+
209
  function resetSession() {
210
  if (!bootstrapData) return;
211
+ bumpSessionRevision();
212
  clearTurnWatchdog();
213
  clearSavedSession();
214
  session = defaultSession(bootstrapData);
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");
 
229
  renderPlan([]);
230
  renderProjects(bootstrapData.top_projects || []);
231
  renderWhitespace(bootstrapData.whitespace || []);
232
+ restoreExportButtonLabels();
233
  exportButton.disabled = true;
234
  setButtonDisabled(exportNotesButton, true);
235
  setButtonDisabled(exportChapterButton, true);
 
238
  }
239
 
240
  async function loadDemoSession() {
241
+ bumpSessionRevision();
242
  submit.disabled = true;
243
  setCommandDisabled(true);
244
  ink.classList.remove("bleed", "gold");
 
546
  if (!ideaId || !Array.isArray(session.ideas)) return;
547
  const idea = session.ideas.find((item) => item.id === ideaId);
548
  if (!idea) return;
549
+ bumpSessionRevision();
550
  session.current_idea_id = idea.id;
551
  if (Array.isArray(idea.targets) && idea.targets.length) {
552
  session.targets = targetOptions.filter((option) => idea.targets.includes(option));
 
780
 
781
  async function exportMarkdown({ endpoint, filename, button, busyLabel, pendingLabel, successLabel }) {
782
  if (!button || button.disabled) return;
783
+ const revision = sessionRevision;
784
  const idleLabel = button.textContent;
785
  button.disabled = true;
786
  button.textContent = busyLabel;
 
795
  const data = Array.isArray(result.data) ? result.data[0] : result.data;
796
  const text = String(data || "");
797
  if (!text.trim()) throw new Error("empty export");
798
+ if (!isCurrentSessionRevision(revision)) return;
799
  downloadText(filename, text, "text/markdown;charset=utf-8");
800
  session.ui_status = `${successLabel}: ${filename}`;
801
  corrections.textContent = session.ui_status;
802
  } catch (error) {
803
+ if (!isCurrentSessionRevision(revision)) return;
804
  session.ui_status = `Export failed: ${error.message}`;
805
  corrections.textContent = session.ui_status;
806
  } finally {
 
807
  button.textContent = idleLabel;
808
+ if (!isCurrentSessionRevision(revision)) return;
809
+ saveSession();
810
  setCommandDisabled(false);
811
  }
812
  }