From 45ae1fbadb49a660d7ec551dc0dcd62db8695114 Mon Sep 17 00:00:00 2001 From: emilymichaels Date: Wed, 9 Feb 2022 00:26:48 +0000 Subject: [PATCH] Bug 1749038 - Adding a keyboard command to toggle narrate in reader mode. r=niklas,mtigley Differential Revision: https://phabricator.services.mozilla.com/D136068 --- .../components/narrate/NarrateControls.jsm | 28 +++++++++++--- .../narrate/test/NarrateTestUtils.jsm | 4 +- toolkit/components/narrate/test/browser.ini | 1 + .../narrate/test/browser_narrate_toggle.js | 37 +++++++++++++++++++ .../en-US/chrome/global/narrate.properties | 8 +++- 5 files changed, 68 insertions(+), 10 deletions(-) create mode 100644 toolkit/components/narrate/test/browser_narrate_toggle.js diff --git a/toolkit/components/narrate/NarrateControls.jsm b/toolkit/components/narrate/NarrateControls.jsm index e17b22adb1b4..bfb1a70474d6 100644 --- a/toolkit/components/narrate/NarrateControls.jsm +++ b/toolkit/components/narrate/NarrateControls.jsm @@ -35,7 +35,7 @@ function NarrateControls(win, languagePromise) { let elemL10nMap = { ".narrate-skip-previous": "back", - ".narrate-start-stop": "start", + ".narrate-start-stop": "start-label", ".narrate-skip-next": "forward", ".narrate-rate-input": "speed", }; @@ -86,6 +86,12 @@ function NarrateControls(win, languagePromise) { narrateStartStop.className = "narrate-start-stop"; narrateControl.appendChild(narrateStartStop); + win.document.addEventListener("keydown", function(event) { + if (win.document.hasFocus() && event.key === "n") { + narrateStartStop.click(); + } + }); + let narrateSkipNext = win.document.createElement("button"); narrateSkipNext.className = "narrate-skip-next"; narrateSkipNext.disabled = true; @@ -101,9 +107,16 @@ function NarrateControls(win, languagePromise) { narrateRate.appendChild(narrateRateInput); for (let [selector, stringID] of Object.entries(elemL10nMap)) { - dropdown - .querySelector(selector) - .setAttribute("title", gStrings.GetStringFromName(stringID)); + if (selector === ".narrate-start-stop") { + let shortcut = gStrings.GetStringFromName("narrate-key-shortcut"); + let label = gStrings.formatStringFromName(stringID, [shortcut]); + + dropdown.querySelector(selector).setAttribute("title", label); + } else { + dropdown + .querySelector(selector) + .setAttribute("title", gStrings.GetStringFromName(stringID)); + } } this.narrator = new Narrator(win, languagePromise); @@ -277,8 +290,11 @@ NarrateControls.prototype = { dropdown.classList.toggle("speaking", speaking); let startStopButton = this._doc.querySelector(".narrate-start-stop"); - startStopButton.title = gStrings.GetStringFromName( - speaking ? "stop" : "start" + let shortcutId = gStrings.GetStringFromName("narrate-key-shortcut"); + + startStopButton.title = gStrings.formatStringFromName( + speaking ? "stop-label" : "start-label", + [shortcutId] ); this._doc.querySelector(".narrate-skip-previous").disabled = !speaking; diff --git a/toolkit/components/narrate/test/NarrateTestUtils.jsm b/toolkit/components/narrate/test/NarrateTestUtils.jsm index ed0fd33d239b..1be38b4a373a 100644 --- a/toolkit/components/narrate/test/NarrateTestUtils.jsm +++ b/toolkit/components/narrate/test/NarrateTestUtils.jsm @@ -52,7 +52,7 @@ var NarrateTestUtils = { ok(!!$(this.START), "start button is showing"); ok(!$(this.STOP), "stop button is hidden"); // This checks for a localized label. Not the best... - ok($(this.START).title == "Start", "Button tooltip is correct"); + ok($(this.START).title == "Start (N)", "Button tooltip is correct"); }, isStartedState(window, ok) { @@ -62,7 +62,7 @@ var NarrateTestUtils = { ok(!$(this.START), "start button is hidden"); ok(!!$(this.STOP), "stop button is showing"); // This checks for a localized label. Not the best... - ok($(this.STOP).title == "Stop", "Button tooltip is correct"); + ok($(this.STOP).title == "Stop (N)", "Button tooltip is correct"); }, selectVoice(window, voiceUri) { diff --git a/toolkit/components/narrate/test/browser.ini b/toolkit/components/narrate/test/browser.ini index 0f5d694ac2a4..5157179d7594 100644 --- a/toolkit/components/narrate/test/browser.ini +++ b/toolkit/components/narrate/test/browser.ini @@ -10,3 +10,4 @@ support-files = support-files = inferno.html [browser_voiceselect.js] [browser_word_highlight.js] +[browser_narrate_toggle.js] diff --git a/toolkit/components/narrate/test/browser_narrate_toggle.js b/toolkit/components/narrate/test/browser_narrate_toggle.js new file mode 100644 index 000000000000..498c6fb1ef41 --- /dev/null +++ b/toolkit/components/narrate/test/browser_narrate_toggle.js @@ -0,0 +1,37 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + +// This test verifies that the keyboard shortcut "n" will Start/Stop the +// narration of an article in readermode when the article is in focus. + +registerCleanupFunction(teardown); + +add_task(async function testToggleNarrate() { + setup(); + + await spawnInNewReaderTab(TEST_ARTICLE, async function() { + let $ = content.document.querySelector.bind(content.document); + + await NarrateTestUtils.waitForNarrateToggle(content); + + let eventUtils = NarrateTestUtils.getEventUtils(content); + + NarrateTestUtils.isStoppedState(content, ok); + + $(NarrateTestUtils.TOGGLE).focus(); + eventUtils.synthesizeKey("n", {}, content); + + await ContentTaskUtils.waitForEvent(content, "paragraphstart"); + NarrateTestUtils.isStartedState(content, ok); + + $(NarrateTestUtils.TOGGLE).focus(); + eventUtils.synthesizeKey("n", {}, content); + + await ContentTaskUtils.waitForCondition( + () => !$(NarrateTestUtils.STOP), + "transitioned to stopped state" + ); + NarrateTestUtils.isStoppedState(content, ok); + }); +}); diff --git a/toolkit/locales/en-US/chrome/global/narrate.properties b/toolkit/locales/en-US/chrome/global/narrate.properties index 87f5e09c0284..e5afd5bcb789 100644 --- a/toolkit/locales/en-US/chrome/global/narrate.properties +++ b/toolkit/locales/en-US/chrome/global/narrate.properties @@ -7,8 +7,12 @@ # of the feature and it is the label for the popup button. listen = Listen back = Back -start = Start -stop = Stop +# %S is the keyboard shortcut for the start command +start-label = Start (%S) +# %S is the keyboard shortcut for the stop command +stop-label = Stop (%S) +# Keyboard shortcut to toggle the narrate feature +narrate-key-shortcut = N forward = Forward speed = Speed selectvoicelabel = Voice: