From 31b3474f8f5ce738353a9d959ea1f40cc48675c4 Mon Sep 17 00:00:00 2001 From: gator Date: Thu, 17 Sep 2026 02:48:38 +0000 Subject: [PATCH] book.html: list the trailers already run, because there was no way back Once you navigated away from a trailer, the only route back to it was the URL. The page offered a way to start work and no way to return to it, which meant every finished run was effectively lost the moment you closed the tab. The list leads with what someone actually wants to know at a glance - is it finished, did every writer survive, has anything been drawn, what has it cost - rather than with an id and a timestamp. A run still working shows what it is doing and keeps polling, so this is also the page you land on to check progress. trailer.html gets a link back, so the two pages are a loop rather than a one-way trip. --- book.html | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 60 insertions(+), 2 deletions(-) diff --git a/book.html b/book.html index 2763094..f855bac 100644 --- a/book.html +++ b/book.html @@ -34,6 +34,18 @@ .wr.on{border-color:var(--accent)} .wr input{margin:0} .lead{margin-left:6px;font-size:12px;color:var(--muted)} + .run{display:flex;gap:14px;align-items:center;padding:14px 0; + border-top:1px solid var(--line);flex-wrap:wrap} + .run:first-child{border-top:0} + .run .meta{flex:1;min-width:220px} + .run h3{margin:0 0 3px;font-size:16px} + .run .sub{color:var(--muted);font-size:13px} + .run .who{color:var(--muted);font-size:12px;margin-top:2px} + .dot{font-size:12px;padding:2px 8px;border-radius:999px;border:1px solid var(--line); + color:var(--muted)} + .dot.done{color:var(--accent2);border-color:var(--accent2)} + .dot.work{color:var(--accent);border-color:var(--accent)} + .dot.bad{color:#e0685f;border-color:#e0685f} @@ -44,6 +56,13 @@

Upload the manuscript and say what you want the trailer to do. Several models each read the whole book and write their own cinematic trailer — script, cast and shot list. You read them side by side, mark up the shots you want changed, and let them critique each other before one gets filmed.

+ +
@@ -129,7 +148,45 @@ function readFileB64(file) { navBar("trailer"); var BOOKS = [], PICKED = null, WRITERS = [], CHOSEN = {}, LEAD = "", EDIT = null; - var pollTimer = null; + var pollTimer = null, runTimer = null; + + // ---------------------------------------------------------------- runs + + function runHtml(r) { + var bits = []; + if (r.ready) bits.push(r.ready + " written"); + if (r.drawn) bits.push(r.drawn + " drawn"); + if (r.failed) bits.push(r.failed + " failed"); + if (r.cost_usd) bits.push("$" + Number(r.cost_usd).toFixed(2)); + if (r.created_at) bits.push(when(r.created_at)); + + var cls = r.busy ? "work" : (r.failed && !r.ready ? "bad" : "done"); + var word = r.busy ? "working" : (r.stage || ""); + + return '
' + + '

' + esc(r.book_title || "Untitled") + '

' + + '
' + esc(bits.join(" ยท ")) + '
' + + '
' + esc(r.writers || "") + + (r.lead_writer ? ' · lead: ' + esc(r.lead_writer) : '') + '
' + + '
' + + '' + esc(word) + '' + + '' + + (r.busy ? "Watch" : "Review") + '' + + '
'; + } + + async function loadRuns() { + var r = await api("list_runs", {}); + if (!r.ok) return; + var runs = r.runs || []; + document.getElementById("runsec").style.display = runs.length ? "" : "none"; + document.getElementById("runs").innerHTML = runs.map(runHtml).join(""); + // A run that is still writing or drawing is worth watching from here, so + // this doubles as the progress page. + var busy = runs.some(function (x) { return x.busy; }); + if (busy && !runTimer) runTimer = setInterval(loadRuns, 8000); + if (!busy && runTimer) { clearInterval(runTimer); runTimer = null; } + } // ---------------------------------------------------------------- books @@ -207,7 +264,7 @@ function readFileB64(file) { t.disabled = true; var u = await api("update_book", { book_id: save, title: title, author: author }); if (!u.ok) { showMsg("msg", u.error || "That did not save."); t.disabled = false; return; } - hideMsg("msg"); EDIT = null; loadBooks(); + hideMsg("msg"); EDIT = null; loadBooks(); loadRuns(); return; } if (pick) { PICKED = pick; hideMsg("msg"); paintBooks(); paintQuote(); return; } @@ -344,6 +401,7 @@ function readFileB64(file) { }); loadBooks(); + loadRuns(); })();