Stop click/drag-on-a-name from reassigning the wrong paragraph (v1.14.13)
The intended flow is: click the broken paragraph's speaker label to open "Assign to", then supply the name (type, click it anywhere in the text, or drag-select it). But clicking or drag-selecting a name with no popup open yet used to open/target a popup for whichever paragraph that name lived in, silently reassigning THAT paragraph instead of the one the user meant to fix. Both paths now require an already-open popup before they do anything — a paragraph is only ever selected via its own speaker label (or the existing double-click fast-assign shortcut). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
3db3616830
commit
cd20df315d
@ -9,6 +9,13 @@ Follows [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) · versioned wi
|
||||
|
||||
---
|
||||
|
||||
## [1.14.13] — 2026-07-09
|
||||
|
||||
### Fixed
|
||||
- **Clicking or drag-selecting a name could reassign the wrong paragraph** — the intended flow is: click the broken (Unknown/Narrator/misattributed) paragraph's speaker label first to open "Assign to", *then* supply the name by typing, clicking it anywhere in the text, or drag-selecting it. But clicking/dragging a name with no popup open yet used to open (and target) the popup for whichever paragraph that name happened to live in — silently reassigning that paragraph instead of the one the user meant to fix. Clicking/dragging a name now only ever fills an already-open popup; a paragraph is only ever selected via its own speaker label (or the existing double-click-a-name fast-assign shortcut).
|
||||
|
||||
---
|
||||
|
||||
## [1.14.12] — 2026-07-09
|
||||
|
||||
### Added
|
||||
|
||||
@ -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.14.12">
|
||||
<meta name="app-version" content="1.14.13">
|
||||
<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.14.12">
|
||||
<link rel="stylesheet" href="/static/style.css?v=1.14.13">
|
||||
|
||||
|
||||
<!-- ── Flag icons — non-blocking (loaded async, icons appear after JS) ── -->
|
||||
@ -365,7 +365,7 @@ window.toggleNavTree = function(treeId, chevronId) {
|
||||
</script>
|
||||
|
||||
<!-- loader.js: fetches sections → loads JS modules → removes skeleton -->
|
||||
<script src="/static/loader.js?v=1.14.12"></script>
|
||||
<script src="/static/loader.js?v=1.14.13"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@ -2797,28 +2797,26 @@ STRIKTE FORMAT- UND TEXTREGELN:
|
||||
_abOpenAssignPopup(spk.closest('.ab-cv-row'), spk, '');
|
||||
return;
|
||||
}
|
||||
// Click a name/word inside the narration text itself — same popup,
|
||||
// pre-filled with the clicked word so you don't have to retype it.
|
||||
// Dragging across several words is handled by the native-selection
|
||||
// listener below instead of a custom span-drag tracker, so it can't
|
||||
// conflict with the existing "select text to split this segment" flow,
|
||||
// which also reacts to window.getSelection() over the same text. That
|
||||
// listener clears the selection once it acts, so this guard (rather than
|
||||
// just isCollapsed) stops the click that follows a drag's mouseup from
|
||||
// re-opening the popup with just the single word under the pointer.
|
||||
// This guard (rather than just isCollapsed) stops the click that follows
|
||||
// a drag's mouseup from also firing the word-click branch below.
|
||||
if (_abJustHandledSelection) { _abJustHandledSelection = false; return; }
|
||||
const txtEl = e.target.closest('.ab-cv-txt');
|
||||
if (txtEl && window.getSelection().isCollapsed) {
|
||||
// Clicking a name/word never opens or retargets a popup by itself —
|
||||
// only the speaker label (handled above) selects a paragraph. This
|
||||
// requires an assign popup to already be open (via that label click,
|
||||
// or a double-click fast-assign): a click on a name anywhere in the
|
||||
// text then just borrows that name into the search box, targeting
|
||||
// whichever paragraph was actually selected. Without this, clicking a
|
||||
// name that happens to live in some OTHER paragraph's text (the
|
||||
// common way to "grab a name I see") silently reassigned THAT
|
||||
// paragraph instead of the one the user meant to fix.
|
||||
if (!assignModeRow) return;
|
||||
const row = txtEl.closest('.ab-cv-row');
|
||||
const nameHit = e.target.closest('.ab-name-hit');
|
||||
const clickedWord = nameHit ? (nameHit.dataset.name || nameHit.textContent.trim())
|
||||
: _abWordRangeAtPoint(e.clientX, e.clientY)?.word;
|
||||
// If a popup is already open targeting a DIFFERENT paragraph, a click on
|
||||
// a name elsewhere in the text only borrows that name into the search
|
||||
// box — it must not silently retarget/highlight the paragraph under the
|
||||
// cursor, which used to make it look like THAT paragraph was being
|
||||
// reassigned instead of the one the user actually opened the popup for.
|
||||
if (assignModeRow && assignModeRow !== row) {
|
||||
if (assignModeRow !== row) {
|
||||
if (clickedWord) {
|
||||
const inp = assignPopup.querySelector('input');
|
||||
inp.value = clickedWord;
|
||||
@ -3003,23 +3001,14 @@ STRIKTE FORMAT- UND TEXTREGELN:
|
||||
// alone for the "Split text to Unknown Speaker" button (wired via
|
||||
// selectionchange below) instead of hijacking them into the assign popup.
|
||||
if (/^[»„“"'‘]/.test(text)) return;
|
||||
// Dragging to select a name only ever feeds an ALREADY-open popup (opened
|
||||
// by clicking a paragraph's speaker label) — it must not open/retarget a
|
||||
// popup for whichever paragraph happens to contain the dragged text,
|
||||
// which used to reassign the wrong paragraph (the one you dragged a name
|
||||
// out of, not the one you actually meant to fix).
|
||||
if (!assignModeSeg) return;
|
||||
_abJustHandledSelection = true; // stop the click that follows this mouseup from also firing
|
||||
if (assignModeSeg) {
|
||||
// Popup already open (e.g. from clicking the speaker label) — a short
|
||||
// selection refines/confirms the assignment directly, as before.
|
||||
assignName(text);
|
||||
sel.removeAllRanges();
|
||||
return;
|
||||
}
|
||||
// No popup yet: dragging across a name inside the narration text (e.g. a
|
||||
// multi-word name like "Sharraz Garthai" the roster doesn't have) opens
|
||||
// the popup pre-filled with the dragged text instead of doing nothing.
|
||||
const anchorEl = sel.anchorNode.nodeType === 3 ? sel.anchorNode.parentNode : sel.anchorNode;
|
||||
const txtSpan = anchorEl.closest('.ab-cv-txt');
|
||||
if (!txtSpan) { _abJustHandledSelection = false; return; }
|
||||
const row = txtSpan.closest('.ab-cv-row');
|
||||
if (!row) { _abJustHandledSelection = false; return; }
|
||||
_abOpenAssignPopup(row, anchorEl, text);
|
||||
assignName(text);
|
||||
sel.removeAllRanges();
|
||||
});
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user