From 07eadeff1e1eea8d93c0936c2aa05a2a50dfb209 Mon Sep 17 00:00:00 2001 From: mARTin-B78 Date: Mon, 6 Jul 2026 14:35:27 +0200 Subject: [PATCH] Fix Recast-selected running on the full roster, improve dropdown positioning (v1.13.7) csForReaderSelective passed the ENTIRE roster to csGenerate as the target list, so the "N cast characters queued" progress dialog showed every character regardless of what was actually checked in the picker - only the final save step was correctly filtered, making the whole run look like it ignored the selection. Now only the picked name(s) go in as the target roster. Also fixed the "Recast options" dropdown opening off-screen: its anchor sits in the bottom action bar, so opening downward (the default) routinely pushed it past the viewport edge. Opens upward when there isn't enough room below, with more prominent styling. Co-Authored-By: Claude Fable 5 --- CHANGELOG.md | 8 ++++++++ VERSION | 2 +- static/index.html | 6 +++--- static/js/audiobook.js | 9 ++++++++- static/js/character-sheets.js | 8 ++++++-- static/style.css | 9 +++++---- 6 files changed, 31 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6bd5586..1508d03 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,14 @@ Follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) · versioned wi --- +## [1.13.7] — 2026-07-06 + +### Fixed +- **"Recast selected" showed every character as queued, not just the ones picked** — the progress dialog looked exactly like a full recast because it was passed the entire roster as the target list; the selection only actually took effect at the final save step. Now only the picked character(s) go in as the target roster, so the dialog accurately shows just those as queued. +- **"Recast options" dropdown routinely opened off-screen** — its anchor button sits in the bottom action bar, so the menu opening downward (the default) was often pushed past the viewport edge, barely visible. It now opens upward when there isn't enough room below, and is styled more prominently. + +--- + ## [1.13.6] — 2026-07-06 ### Fixed diff --git a/VERSION b/VERSION index 2e3a551..b0f139e 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.13.6 +1.13.7 diff --git a/static/index.html b/static/index.html index ff8892f..497a66a 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/audiobook.js b/static/js/audiobook.js index d2c312e..9afed87 100644 --- a/static/js/audiobook.js +++ b/static/js/audiobook.js @@ -1048,7 +1048,14 @@ function _abOpenRecastCharsMenu(anchorEl, bookTitle, existingChars) { ''; document.body.appendChild(menu); const rect = anchorEl.getBoundingClientRect(); - menu.style.top = (rect.bottom + 4) + 'px'; + // The anchor button sits in the panel's bottom action bar, so opening + // downward (the default) routinely pushed this near/past the viewport's + // bottom edge — barely visible, overlapping the page footer. Open upward + // instead whenever there isn't comfortably enough room below. + const menuH = 90; // ~2 rows, enough for this fixed 2-item menu + const openUp = rect.bottom + menuH + 12 > window.innerHeight; + menu.style.top = openUp ? '' : (rect.bottom + 4) + 'px'; + menu.style.bottom = openUp ? (window.innerHeight - rect.top + 4) + 'px' : ''; menu.style.left = Math.max(10, rect.right - 190) + 'px'; const close = () => { menu.remove(); document.removeEventListener('mousedown', onDoc); }; const onDoc = (e) => { if (!menu.contains(e.target) && e.target !== anchorEl) close(); }; diff --git a/static/js/character-sheets.js b/static/js/character-sheets.js index 02c9c50..c6c1824 100644 --- a/static/js/character-sheets.js +++ b/static/js/character-sheets.js @@ -788,8 +788,12 @@ async function csForReaderSelective(selectedNames) { if (!wanted.size) { toast('No characters selected', 'error'); return; } const text = csReaderText(); const book = readerState.title || 'Untitled book'; - const knownRoster = csKnownReaderRoster(); - const sheets = await csGenerate(text, null, knownRoster); + // Only the picked names go in as the target roster — passing the FULL + // roster here (like csForReader does) made the progress dialog show every + // character as "queued" even though just one or two were selected, which + // read as "it's recasting everyone" even though the save step at the end + // was already correctly filtered down to the picks. + const sheets = await csGenerate(text, null, selectedNames); if (!sheets) return; const filtered = sheets.filter(s => wanted.has(String(s.name || '').trim().toLowerCase())); if (!filtered.length) { toast('None of the selected characters turned up in this pass — try again or pick different ones', 'error'); return; } diff --git a/static/style.css b/static/style.css index 82d33bd..2b46245 100644 --- a/static/style.css +++ b/static/style.css @@ -5658,13 +5658,14 @@ code { background: var(--panel); border-radius: 4px; padding: 1px 5px; font-fami .ab-cv-castchars-group .ab-cv-castchars-menu { border-radius: 0 6px 6px 0; border-left: 0; padding: 0 8px; } .ab-recast-menu { position: fixed; z-index: 2001; background: var(--surface); border: 1px solid var(--border); - border-radius: 8px; box-shadow: 0 10px 25px rgba(0,0,0,.3); padding: 4px; min-width: 180px; - display: flex; flex-direction: column; gap: 1px; + border-radius: 8px; box-shadow: 0 10px 30px rgba(0,0,0,.4); padding: 5px; min-width: 200px; + display: flex; flex-direction: column; gap: 2px; } .ab-recast-menu button { - display: flex; align-items: center; gap: 8px; padding: 7px 10px; font-size: 12.5px; - border: none; background: none; color: var(--text); border-radius: 5px; cursor: pointer; text-align: left; + display: flex; align-items: center; gap: 9px; padding: 9px 11px; font-size: 13px; font-weight: 600; + border: none; background: none; color: var(--text); border-radius: 6px; cursor: pointer; text-align: left; } +.ab-recast-menu button .mdi { font-size: 16px; color: var(--accent); } .ab-recast-menu button:hover { background: var(--panel); } .ab-recast-select-list { max-height: 280px; overflow-y: auto; margin: 10px 0; text-align: left; border: 1px solid var(--border); border-radius: 6px; padding: 4px; } .ab-recast-select-list label { display: flex; align-items: center; gap: 8px; padding: 5px 6px; cursor: pointer; font-size: 13px; border-radius: 4px; }