From 83ad5da5f11f39cf3679573dead2ac012d61e2e4 Mon Sep 17 00:00:00 2001 From: Abe Jellinek <1770299+AbeJellinek@users.noreply.github.com> Date: Thu, 19 Mar 2026 13:44:23 -0400 Subject: [PATCH] Toggle reading on Accel-Alt-R/L --- src/common/context-menu.js | 5 ++++- src/common/keyboard-manager.js | 2 +- src/common/reader.js | 17 ++++++++++++++--- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/common/context-menu.js b/src/common/context-menu.js index d8e2cc986..d4778bb1f 100644 --- a/src/common/context-menu.js +++ b/src/common/context-menu.js @@ -199,7 +199,10 @@ export function createViewContextMenu(reader, params) { { label: reader._getString('reader-read-aloud'), disabled: !params.position || !reader._enableReadAloud, - onCommand: () => reader.startReadAloudAtPosition(params.position) + onCommand: () => reader.startReadAloudAtPosition({ + behavior: 'move', + position: params.position, + }) } ], [ diff --git a/src/common/keyboard-manager.js b/src/common/keyboard-manager.js index 3e6e1f650..e244ffe11 100644 --- a/src/common/keyboard-manager.js +++ b/src/common/keyboard-manager.js @@ -293,7 +293,7 @@ export class KeyboardManager { else if (code === `${pm}-Alt-KeyR` || code === `${pm}-Alt-KeyL`) { event.preventDefault(); event.stopPropagation(); - this._reader.startReadAloudAtPosition(); + this._reader.startReadAloudAtPosition({ behavior: 'toggle' }); } else if (['Delete', 'Backspace'].includes(key)) { // Prevent the deletion of annotations when they are selected and the focus is within diff --git a/src/common/reader.js b/src/common/reader.js index f7c2ae035..a90e8d8fb 100644 --- a/src/common/reader.js +++ b/src/common/reader.js @@ -989,14 +989,25 @@ class Reader { this._handleReadAloudStateChange({ paused }); } - startReadAloudAtPosition(position = null) { + /** + * @param {'move' | 'toggle'} behavior If 'move', always start Read Aloud, or move the reading position. + * If 'toggle', use smart toggle logic: when there's a selection, move to it; otherwise, close Read Aloud. + * @param {Position | null} position + */ + startReadAloudAtPosition({ behavior = 'move', position = null } = {}) { if (!this._enableReadAloud) { return; } - if (!position && this._state[this._lastView + 'SelectionPopup']) { - position = this._state[this._lastView + 'SelectionPopup'].annotation?.position; + let selectionPosition = this._state[this._lastViewPrimary ? 'primaryViewSelectionPopup' : 'secondaryViewSelectionPopup'] + ?.annotation?.position; + if (!position && selectionPosition) { + position = selectionPosition; } position ??= null; + if (behavior === 'toggle' && !position && this._state.readAloudState.popupOpen) { + this.toggleReadAloudPopup(false); + return; + } this._handleReadAloudStateChange({ popupOpen: true, active: true,