Open toolbar flyout menus downwards when there is room (v1.20.18)
The Identify/Cast flyouts were hard-anchored to open above their trigger, which suited the casting panel's bottom footer but clipped them off the top of the screen in Studio, where the same toolbar sits near the top — the first two entries were unreachable. They now pick the side with space, prefer opening downwards, stay clamped inside the viewport and scroll if taller than it. Also reorders the Identify menu to the sequence the passes should run in, with the one-click Auto-repair cast first. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
4c686165b3
commit
30bac15b6e
@ -22,6 +22,12 @@ Follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) · versioned wi
|
||||
- **Emotion instructions are now always written in English**, even for non-English voices (the spoken text and the native-accent clause stay in the book's own language). Confirmed by controlled A/B testing — same line, same voice, only the instruct language varying — that Qwen3-TTS follows English emotion instructions far more reliably: German instructs produced barely-differentiated output, while English instructs yield a clean, correctly-ordered prosodic gradient (whisper 128 Hz → sad 142 → neutral 179 → scared 203 → happy 225 → angry 269 Hz), with sensible duration changes too (sad slowest, scared fastest).
|
||||
- **Fish-Speech generation parameters (`temperature` / `top_p` / `repetition_penalty`) were never forwarded.** Every Fish-Speech line synthesized at the server's fixed defaults, ignoring the app's per-backend stability settings — the only backend not routed through the shared `_apply_tts_extra_params` helper.
|
||||
|
||||
## [1.20.18] — 2026-08-12
|
||||
|
||||
### Fixed
|
||||
- **Toolbar menus opened upwards and were clipped off the top of the screen in Studio.** The Identify / Cast / Cast-view flyouts were hard-anchored to open above their button, which was right when those buttons lived in the casting panel's footer at the bottom of the page — but in Studio the same toolbar sits near the top, so the menu ran off-screen and its first entries were unreachable (confirmed live: "Auto-repair cast" and "Identify all characters" were both hidden). The menu now opens downwards whenever there is room, falls back to upwards when there isn't, is clamped inside the viewport, and scrolls if it is ever taller than the screen.
|
||||
- Identify Characters menu order now matches the order the passes should be run in, with the one-click **Auto-repair cast** first.
|
||||
|
||||
## [1.20.16] — 2026-08-12
|
||||
|
||||
### Added
|
||||
|
||||
4
static/dist/main.min.js
vendored
4
static/dist/main.min.js
vendored
File diff suppressed because one or more lines are too long
@ -10,7 +10,7 @@
|
||||
<meta name="format-detection" content="telephone=no">
|
||||
<meta name="color-scheme" content="light dark">
|
||||
<meta name="theme-color" content="#2563EB">
|
||||
<meta name="app-version" content="1.20.16">
|
||||
<meta name="app-version" content="1.20.18">
|
||||
<link rel="manifest" href="/manifest.webmanifest">
|
||||
<link rel="icon" href="/static/icon.svg" type="image/svg+xml">
|
||||
<link rel="apple-touch-icon" href="/static/icon.svg">
|
||||
@ -27,7 +27,7 @@
|
||||
|
||||
<!-- ── Core styles (local — no CDN dependency for first paint) ────────── -->
|
||||
<link rel="stylesheet" href="/static/vendor/mdi/materialdesignicons.min.css">
|
||||
<link rel="stylesheet" href="/static/style.css?v=1.20.16">
|
||||
<link rel="stylesheet" href="/static/style.css?v=1.20.18">
|
||||
|
||||
|
||||
<!-- ── Flag icons — non-blocking (loaded async, icons appear after JS) ── -->
|
||||
@ -378,7 +378,7 @@ window.toggleNavTree = function(treeId, chevronId) {
|
||||
</script>
|
||||
|
||||
<!-- loader.js: fetches sections → loads JS modules → removes skeleton -->
|
||||
<script src="/static/loader.js?v=1.20.16"></script>
|
||||
<script src="/static/loader.js?v=1.20.18"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@ -1307,7 +1307,21 @@ function _abToggleFootMenu(triggerBtn, items) {
|
||||
document.body.appendChild(el);
|
||||
const rect = triggerBtn.getBoundingClientRect();
|
||||
el.style.left = Math.max(8, Math.min(rect.left, window.innerWidth - el.offsetWidth - 8)) + 'px';
|
||||
el.style.bottom = (window.innerHeight - rect.top + 6) + 'px';
|
||||
// These buttons used to live only in the casting panel's footer at the bottom
|
||||
// of the screen, so the menu was hard-anchored to open upwards. In Studio the
|
||||
// same toolbar sits near the TOP of the page, where opening upwards pushed the
|
||||
// menu off-screen and silently clipped its first entries (confirmed live: the
|
||||
// first two items were unreachable). Pick the side with room, preferring down.
|
||||
const menuH = el.offsetHeight;
|
||||
const spaceBelow = window.innerHeight - rect.bottom;
|
||||
const spaceAbove = rect.top;
|
||||
if (spaceBelow >= menuH + 12 || spaceBelow >= spaceAbove) {
|
||||
el.style.top = Math.min(rect.bottom + 6, Math.max(8, window.innerHeight - menuH - 8)) + 'px';
|
||||
el.style.bottom = 'auto';
|
||||
} else {
|
||||
el.style.bottom = (window.innerHeight - rect.top + 6) + 'px';
|
||||
el.style.top = 'auto';
|
||||
}
|
||||
el.querySelectorAll('.ab-foot-menu-item').forEach((btn) => {
|
||||
btn.addEventListener('click', () => {
|
||||
const it = items[Number(btn.dataset.idx)];
|
||||
@ -4166,10 +4180,10 @@ ABSOLUTE REGELN:
|
||||
const castMenu = foot.querySelector('#ab-cv-menu-cast');
|
||||
const viewCastMenu = foot.querySelector('#ab-cv-menu-viewcast');
|
||||
identifyMenu?.addEventListener('click', () => _abToggleFootMenu(identifyMenu, [
|
||||
{ icon: 'mdi-auto-fix', label: 'Auto-repair cast', title: 'Runs the repair sequence automatically: fix mislabeled dialogue, resolve unknown speakers, repeat while it helps, then a full verification only if still needed', onClick: () => audiobookAutoRepairCast() },
|
||||
{ icon: 'mdi-refresh', label: 'Identify all characters', title: 'Scan the text and build the cast list from scratch', onClick: runIdentifyAll, danger: true },
|
||||
{ icon: 'mdi-comment-alert-outline', label: 'Repair mislabeled dialogue', title: 'Finds spoken lines that were typed as narration (usually because the » « quote marks were lost in extraction) and re-checks only those — far cheaper than verifying every narration line', onClick: runRepairNarration },
|
||||
{ icon: 'mdi-account-question-outline', label: 'Identify unknown characters', title: 'Re-scan only the unknown segments with the current prompt', onClick: runIdentifyUnknown },
|
||||
{ icon: 'mdi-auto-fix', label: 'Auto-repair cast', title: 'Runs the repair sequence automatically: fix mislabeled dialogue, resolve unknown speakers, repeat while it helps, then a full verification only if still needed', onClick: () => audiobookAutoRepairCast() },
|
||||
{ icon: 'mdi-repeat', label: 'Run until < N unknown…', title: 'Repeats recast-unknown + narrator-verify passes automatically until the Unknown-speaker count drops below a target, or progress stalls', onClick: () => {
|
||||
const input = window.prompt('Stop once fewer than this many Unknown speakers remain:', '10');
|
||||
if (input == null) return;
|
||||
|
||||
@ -6320,6 +6320,7 @@ code { background: var(--panel); border-radius: 4px; padding: 1px 5px; font-fami
|
||||
.ab-foot-trigger.is-menu-open { border-color: var(--accent); color: var(--accent); }
|
||||
.ab-foot-menu {
|
||||
position: fixed; z-index: 2002; min-width: 240px; max-width: 320px;
|
||||
max-height: calc(100vh - 24px); overflow-y: auto;
|
||||
background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
|
||||
box-shadow: 0 10px 25px rgba(0,0,0,.35); padding: 6px; display: flex; flex-direction: column; gap: 2px;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user