diff --git a/CHANGELOG.md b/CHANGELOG.md index 7af5821..d871815 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,13 @@ Follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) · versioned wi --- +## [1.14.16] — 2026-07-09 + +### Changed +- **Redesigned the Character sheets progress modal** — was a small (420px) dialog with a collapsible single-line JSON preview and a cramped chip grid. Now a large panel (like the audiobook casting live view): the passage currently being analysed on the left, the LLM's live JSON output filling in on the right, and a character sidebar on the right edge with the character(s) just updated highlighted — so you can watch each sheet actually being built from its source text. + +--- + ## [1.14.15] — 2026-07-09 ### Added diff --git a/VERSION b/VERSION index 32f1112..9631867 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.14.15 +1.14.16 diff --git a/static/index.html b/static/index.html index 304c778..c22025e 100644 --- a/static/index.html +++ b/static/index.html @@ -10,7 +10,7 @@ - + @@ -27,7 +27,7 @@ - + @@ -365,7 +365,7 @@ window.toggleNavTree = function(treeId, chevronId) { - + diff --git a/static/js/character-sheets.js b/static/js/character-sheets.js index a9a31c5..1021382 100644 --- a/static/js/character-sheets.js +++ b/static/js/character-sheets.js @@ -314,7 +314,7 @@ async function csGenerate(text, cacheKey, initialRoster) { ? `${knownTotal} cast characters queued · ${detailed} profiles with details` : `${map.size} characters found`; prog.update(i, `Passage ${i + 1} / ${chunks.length}…`, charLabel, csProgressSnapshot(map)); - prog.startPassage(); + prog.startPassage(chunks[i]); try { const body = { text: chunks[i], known_characters: roster.slice(0, 120), target_mode: targetMode, existing: csExistingSummary(map), language, llm_url, model }; let data = null; @@ -368,15 +368,32 @@ function csProgress(total) { if (!ov) { ov = document.createElement('div'); ov.id = 'cs-progress'; ov.className = 'audiobook-overlay'; - ov.innerHTML = `
-
Character sheets
-
Analysing…
-
-
- Live output watching… -

-      
-
+ // Big two-pane layout, mirroring the audiobook casting live view: the + // passage being analysed on the left, the LLM's raw JSON output filling + // in live on the right, and a character sidebar (current one highlighted) + // so the user can watch each sheet actually being built. + ov.innerHTML = `
+
+
Character sheets
+
Analysing…
+
+
+
+
+
+
Passage
+

+          
+
+
Live output watching…
+

+          
+
+
+
Characters found
+
+
+
`; document.body.appendChild(ov); @@ -386,13 +403,16 @@ function csProgress(total) { const fill = ov.querySelector('#cs-progress-fill'); const msg = ov.querySelector('#cs-progress-msg'); const chars = ov.querySelector('#cs-progress-chars'); + const sideTitle = ov.querySelector('#cs-progress-side-title'); + const passagePre = ov.querySelector('#cs-progress-passage-pre'); const livePre = ov.querySelector('#cs-progress-live-pre'); const liveStatus = ov.querySelector('#cs-progress-live-status'); return { - // Called once per passage before its request starts, so the live-output - // pane is empty and honestly labelled before we know whether this model - // streams real content or the request falls back to the blocking path. - startPassage() { + // Called once per passage before its request starts, so both panes are + // reset and honestly labelled before we know whether this model streams + // real content or the request falls back to the blocking path. + startPassage(text) { + if (passagePre) passagePre.textContent = text || ''; if (livePre) livePre.textContent = ''; if (liveStatus) { liveStatus.textContent = 'watching…'; liveStatus.className = 'cs-progress-live-status'; } }, @@ -411,26 +431,22 @@ function csProgress(total) { update(d, label, charLabel, roster = []) { if (fill) fill.style.width = (d / total * 100) + '%'; if (msg && label) msg.textContent = label; + if (sideTitle) sideTitle.textContent = charLabel || 'Characters found'; if (chars) { const list = Array.isArray(roster) ? roster : []; - chars.innerHTML = ` -
${escHtml(charLabel || '')}
- ${list.length ? `
- ${list.map(c => ` -
- ${escHtml((c.name || '?')[0].toUpperCase())} - - ${escHtml(c.name || 'Unknown')} - ${c.alias ? `${escHtml(c.alias)}` : ''} - - - - - ${c.status ? `${escHtml(c.status)}` : ''} -
- `).join('')} -
` : ''} - `; + chars.innerHTML = list.length ? list.map(c => ` +
+ ${escHtml((c.name || '?')[0].toUpperCase())} + + ${escHtml(c.name || 'Unknown')} + ${c.alias ? `${escHtml(c.alias)}` : ''} + + + + + ${c.status ? `${escHtml(c.status)}` : ''} +
+ `).join('') : '
reading…
'; } }, done() { ov.style.display = 'none'; }, diff --git a/static/style.css b/static/style.css index cdffbd9..ebb9812 100644 --- a/static/style.css +++ b/static/style.css @@ -5780,32 +5780,42 @@ code { background: var(--panel); border-radius: 4px; padding: 1px 5px; font-fami } .cs-arc-note { font-size: 11px; color: var(--subtext); margin-top: 3px; font-style: italic; } .cs-progress-box { width: min(520px, 92vw); } -.cs-progress-live { margin-bottom: 10px; border: 1px solid var(--border); border-radius: 8px; } -.cs-progress-live summary { - display: flex; align-items: center; gap: 6px; padding: 7px 10px; font-size: 11.5px; - font-weight: 700; color: var(--subtext); cursor: pointer; list-style: none; +/* Big layout: passage | live output side by side, character sidebar on the + right (current/just-updated characters highlighted) — same shape as the + audiobook casting live view, so you can watch each sheet being built. */ +.cs-progress-box-big { width: min(1400px, 96vw); height: min(880px, 90vh); display: flex; flex-direction: column; padding: 20px 22px; } +.cs-progress-head { flex-shrink: 0; } +.cs-progress-head .audiobook-msg { margin: 8px 0 10px; } +.cs-progress-body { flex: 1; min-height: 0; display: flex; gap: 14px; margin-top: 12px; } +.cs-progress-main { flex: 1; min-width: 0; display: grid; grid-template-columns: 1fr 1fr; gap: 14px; } +.cs-progress-col { min-width: 0; min-height: 0; display: flex; flex-direction: column; gap: 6px; } +.cs-progress-col-label { + display: flex; align-items: center; gap: 6px; font-size: 11px; font-weight: 800; + text-transform: uppercase; letter-spacing: .04em; color: var(--subtext); flex-shrink: 0; } -.cs-progress-live summary::-webkit-details-marker { display: none; } -.cs-progress-live-status { margin-left: auto; font-weight: 500; font-style: italic; opacity: .8; } -.cs-progress-live-status.is-live { color: var(--accent); opacity: 1; } -.cs-progress-live-pre { - margin: 0; padding: 8px 10px; max-height: 160px; overflow-y: auto; white-space: pre-wrap; - overflow-wrap: anywhere; font-size: 11px; line-height: 1.5; color: var(--text); - background: var(--bg); border-top: 1px solid var(--border); -} -.cs-progress-chars { font-size: 11px; color: var(--subtext); min-height: 16px; margin-bottom: 8px; } -.cs-progress-summary { text-align: center; margin-bottom: 8px; color: var(--subtext); } -.cs-progress-list { - display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px; - max-height: 210px; overflow: auto; padding: 2px 2px 4px; +.cs-progress-passage-pre, .cs-progress-live-pre { + flex: 1; min-height: 0; margin: 0; padding: 10px 12px; overflow-y: auto; white-space: pre-wrap; + overflow-wrap: anywhere; font-size: 12px; line-height: 1.55; color: var(--text); + background: var(--bg); border: 1px solid var(--border); border-radius: 8px; } +.cs-progress-live-pre { background: rgba(37,99,235,.05); } +.cs-progress-side { width: 260px; flex-shrink: 0; display: flex; flex-direction: column; gap: 8px; min-height: 0; } +.cs-progress-side-title { font-size: 11px; font-weight: 800; text-transform: uppercase; letter-spacing: .04em; color: var(--subtext); flex-shrink: 0; } +.cs-progress-chars { flex: 1; min-height: 0; overflow-y: auto; display: flex; flex-direction: column; gap: 6px; padding: 2px 2px 4px; } +.cs-progress-empty { font-size: 12px; color: var(--subtext); font-style: italic; text-align: center; padding: 20px 0; } .cs-progress-chip { - display: grid; grid-template-columns: 22px minmax(0, 1fr) 44px auto; align-items: center; gap: 6px; - min-height: 34px; padding: 5px 6px; border: 1px solid var(--border); border-radius: 7px; - background: var(--surface); color: var(--text); + display: grid; grid-template-columns: 26px minmax(0, 1fr) 44px auto; align-items: center; gap: 8px; + min-height: 38px; padding: 6px 8px; border: 1px solid var(--border); border-radius: 8px; + background: var(--surface); color: var(--text); flex-shrink: 0; } .cs-progress-chip.is-new { border-color: rgba(34,197,94,.45); background: rgba(34,197,94,.08); } -.cs-progress-chip.is-updated { border-color: rgba(59,130,246,.45); background: rgba(59,130,246,.08); } +.cs-progress-chip.is-updated { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 10%, transparent); box-shadow: 0 0 0 1px var(--accent); } +@media (max-width: 900px) { + .cs-progress-box-big { width: 96vw; height: 92vh; } + .cs-progress-body { flex-direction: column; } + .cs-progress-main { grid-template-columns: 1fr; } + .cs-progress-side { width: 100%; max-height: 180px; } +} .cs-progress-dot { width: 22px; height: 22px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center; background: var(--accent); color: #fff; font-size: 10px; font-weight: 800;