Bug 1903156 - Remove duplicate code from older menus once the new menus land. r=reader-mode-reviewers,desktop-theme-reviewers,dao,Gijs

Differential Revision: https://phabricator.services.mozilla.com/D218772
This commit is contained in:
Irene Ni
2025-01-01 17:43:17 +00:00
parent c1270e57be
commit ac979c8453
23 changed files with 472 additions and 1407 deletions

View File

@@ -3562,9 +3562,6 @@ pref("reader.content_width", 3);
// The default relative line height in reader mode (1-9)
pref("reader.line_height", 4);
// Determines if improved text and layout menu is enabled in reader mode.
pref("reader.improved_text_menu.enabled", true);
// The default character spacing in reader mode (1-9)
pref("reader.character_spacing", 0);
@@ -3582,9 +3579,6 @@ pref("reader.color_scheme", "auto");
// Color scheme values available in reader mode UI.
pref("reader.color_scheme.values", "[\"auto\",\"light\",\"dark\",\"sepia\",\"contrast\",\"gray\"]");
// Determines if updated color theme menu is enabled in reader mode.
pref("reader.colors_menu.enabled", true);
// The custom color scheme options in reader colors menu.
pref("reader.custom_colors.foreground", "");
pref("reader.custom_colors.background", "");

View File

@@ -16,19 +16,10 @@ export function NarrateControls(win, languagePromise) {
win.addEventListener("unload", this);
let improvedTextMenuEnabled = Services.prefs.getBoolPref(
"reader.improved_text_menu.enabled",
false
);
// Append content style sheet in document head
let style = win.document.createElement("link");
style.rel = "stylesheet";
if (improvedTextMenuEnabled) {
style.href = "chrome://global/skin/narrate-improved.css";
} else {
style.href = "chrome://global/skin/narrate.css";
}
win.document.head.appendChild(style);
let elemL10nMap = {
@@ -62,12 +53,10 @@ export function NarrateControls(win, languagePromise) {
dropdownList.className = "dropdown-popup";
dropdown.appendChild(dropdownList);
if (improvedTextMenuEnabled) {
let narrateHeader = win.document.createElement("h2");
narrateHeader.id = "narrate-header";
narrateHeader.textContent = gStrings.GetStringFromName("read-aloud-header");
dropdownList.appendChild(narrateHeader);
}
let narrateControl = win.document.createElement("div");
narrateControl.className = "narrate-row narrate-control";
@@ -77,17 +66,12 @@ export function NarrateControls(win, languagePromise) {
narrateRate.className = "narrate-row narrate-rate";
dropdownList.appendChild(narrateRate);
let selectLabel = "";
if (improvedTextMenuEnabled) {
let hr = win.document.createElement("hr");
let voiceHeader = win.document.createElement("h2");
voiceHeader.id = "voice-header";
voiceHeader.textContent = gStrings.GetStringFromName("select-voice-header");
dropdownList.appendChild(hr);
dropdownList.appendChild(voiceHeader);
} else {
selectLabel = gStrings.GetStringFromName("selectvoicelabel");
}
let narrateVoices = win.document.createElement("div");
narrateVoices.className = "narrate-row narrate-voices";
@@ -197,7 +181,7 @@ export function NarrateControls(win, languagePromise) {
this.narrator = new Narrator(win, languagePromise);
let branch = Services.prefs.getBranch("narrate.");
this.voiceSelect = new VoiceSelect(win, selectLabel);
this.voiceSelect = new VoiceSelect(win);
this.voiceSelect.element.addEventListener("change", this);
this.voiceSelect.element.classList.add("voice-select");
this.voiceSelect.selectToggle.setAttribute("aria-labelledby", "voice-header");

View File

@@ -2,15 +2,13 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
export function VoiceSelect(win, label) {
export function VoiceSelect(win) {
this._winRef = Cu.getWeakReference(win);
let element = win.document.createElement("div");
element.classList.add("voiceselect");
// TODO: remove unused .label span with Bug 1903156.
// eslint-disable-next-line no-unsanitized/property
element.innerHTML = `<button class="select-toggle" aria-controls="voice-options" aria-expanded="false" role="combobox">
<span class="label">${label}</span> <span class="current-voice"></span>
<span class="current-voice"></span>
</button>
<div class="options" id="voice-options" role="listbox"></div>`;

View File

@@ -9,10 +9,6 @@ import { AppConstants } from "resource://gre/modules/AppConstants.sys.mjs";
const lazy = {};
let gScrollPositions = new Map();
let lastSelectedTheme = "auto";
let improvedTextMenuEnabled = Services.prefs.getBoolPref(
"reader.improved_text_menu.enabled",
false
);
ChromeUtils.defineESModuleGetters(lazy, {
AsyncPrefs: "resource://gre/modules/AsyncPrefs.sys.mjs",
@@ -207,19 +203,9 @@ export var AboutReader = function (
);
// fetch color scheme values from prefs.
let colorsMenuColorSchemeValues = JSON.parse(
let colorSchemeValues = JSON.parse(
Services.prefs.getCharPref("reader.color_scheme.values")
);
// remove contrast and gray options from regular menu.
let colorSchemeValues = [...colorsMenuColorSchemeValues];
colorSchemeValues.splice(colorSchemeValues.length - 2, 2);
let colorsMenuColorSchemeOptions = colorsMenuColorSchemeValues.map(value => ({
l10nId: COLORSCHEME_L10N_IDS[value],
groupName: "color-scheme",
value,
itemClass: value + "-button",
}));
let colorSchemeOptions = colorSchemeValues.map(value => ({
l10nId: COLORSCHEME_L10N_IDS[value],
@@ -229,55 +215,28 @@ export var AboutReader = function (
}));
let colorScheme = Services.prefs.getCharPref("reader.color_scheme");
if (Services.prefs.getBoolPref("reader.colors_menu.enabled", false)) {
doc.getElementById("regular-color-scheme").hidden = true;
doc.getElementById("custom-colors-color-scheme").hidden = false;
this._setupSegmentedButton(
"colors-menu-color-scheme-buttons",
colorsMenuColorSchemeOptions,
colorScheme,
this._setColorSchemePref.bind(this)
);
this._setupCustomColors(
CUSTOM_THEME_COLOR_INPUTS,
"custom-colors-selection",
"about-reader-custom-colors"
);
this._setupButton(
"custom-colors-reset-button",
this._resetCustomColors.bind(this)
);
this._handleThemeFocus();
} else {
this._setupSegmentedButton(
"color-scheme-buttons",
colorSchemeOptions,
colorScheme,
this._setColorSchemePref.bind(this)
);
}
this._setupCustomColors(
CUSTOM_THEME_COLOR_INPUTS,
"custom-colors-selection",
"about-reader-custom-colors"
);
this._setupButton(
"custom-colors-reset-button",
this._resetCustomColors.bind(this)
);
this._handleThemeFocus();
this._setColorSchemePref(colorScheme);
let fontTypeOptions = [
{
l10nId: "about-reader-font-type-sans-serif",
groupName: "font-type",
value: "sans-serif",
itemClass: "sans-serif-button",
},
{
l10nId: "about-reader-font-type-serif",
groupName: "font-type",
value: "serif",
itemClass: "serif-button",
},
];
// TODO: Move font type pref getting alongside other prefs when old menu is retired.
let fontType = Services.prefs.getCharPref("reader.font_type", "sans-serif");
// Differentiates between the tick mark labels for width vs spacing controls
// for localization purposes.
const [standardSpacingLabel, wideSpacingLabel] = lazy.l10n.formatMessagesSync(
@@ -353,10 +312,6 @@ export var AboutReader = function (
textAlignmentOptions = textAlignmentOptions.reverse();
}
if (improvedTextMenuEnabled) {
doc.getElementById("regular-text-menu").hidden = true;
doc.getElementById("improved-text-menu").hidden = false;
let selectorFontTypeValues = ["sans-serif", "serif", "monospace"];
try {
selectorFontTypeValues = JSON.parse(
@@ -368,6 +323,7 @@ export var AboutReader = function (
e.message
);
}
let fontType = Services.prefs.getCharPref("reader.font_type", "sans-serif");
this._setupSelector(
"font-type",
selectorFontTypeValues,
@@ -388,10 +344,7 @@ export var AboutReader = function (
e.message
);
}
let fontWeight = Services.prefs.getCharPref(
"reader.font_weight",
"regular"
);
let fontWeight = Services.prefs.getCharPref("reader.font_weight", "regular");
this._setupSelector(
"font-weight",
fontWeightValues,
@@ -406,9 +359,9 @@ export var AboutReader = function (
"content-width",
contentWidthSliderOptions,
contentWidth,
this._setContentWidthSlider.bind(this)
this._setContentWidth.bind(this)
);
this._setContentWidthSlider(contentWidth);
this._setContentWidth(contentWidth);
let lineSpacing = Services.prefs.getIntPref("reader.line_height", 4);
this._setupSlider(
@@ -458,20 +411,6 @@ export var AboutReader = function (
);
this._handleTextLayoutFocus();
} else {
this._setupSegmentedButton(
"font-type-buttons",
fontTypeOptions,
fontType,
this._setFontType.bind(this)
);
this._setupContentWidthButtons();
this._setupLineHeightButtons();
this._setFontType(fontType);
}
this._setupFontSizeButtons();
@@ -794,15 +733,8 @@ AboutReader.prototype = {
},
_setupFontSizeButtons() {
let plusButton, minusButton;
if (improvedTextMenuEnabled) {
plusButton = this._doc.querySelector(".text-size-plus-button");
minusButton = this._doc.querySelector(".text-size-minus-button");
} else {
plusButton = this._doc.querySelector(".plus-button");
minusButton = this._doc.querySelector(".minus-button");
}
let plusButton = this._doc.querySelector(".text-size-plus-button");
let minusButton = this._doc.querySelector(".text-size-minus-button");
let currentSize = Services.prefs.getIntPref("reader.font_size");
this._setFontSize(currentSize);
@@ -832,18 +764,9 @@ AboutReader.prototype = {
},
_updateFontSizeButtonControls() {
let plusButton, minusButton;
let currentSize = this._fontSize;
if (improvedTextMenuEnabled) {
plusButton = this._doc.querySelector(".text-size-plus-button");
minusButton = this._doc.querySelector(".text-size-minus-button");
} else {
plusButton = this._doc.querySelector(".plus-button");
minusButton = this._doc.querySelector(".minus-button");
let fontValue = this._doc.querySelector(".font-size-value");
fontValue.textContent = currentSize;
}
let plusButton = this._doc.querySelector(".text-size-plus-button");
let minusButton = this._doc.querySelector(".text-size-minus-button");
if (currentSize === this.FONT_SIZE_MIN) {
minusButton.setAttribute("disabled", true);
@@ -865,172 +788,6 @@ AboutReader.prototype = {
this._scheduleToolbarOverlapHandler();
},
_setContentWidth(newContentWidth) {
this._contentWidth = newContentWidth;
this._displayContentWidth(newContentWidth);
let width = 20 + 5 * (this._contentWidth - 1) + "em";
this._doc.body.style.setProperty("--content-width", width);
this._scheduleToolbarOverlapHandler();
return lazy.AsyncPrefs.set("reader.content_width", this._contentWidth);
},
_displayContentWidth(currentContentWidth) {
let contentWidthValue = this._doc.querySelector(".content-width-value");
contentWidthValue.textContent = currentContentWidth;
},
_setupContentWidthButtons() {
const CONTENT_WIDTH_MIN = 1;
const CONTENT_WIDTH_MAX = 9;
let currentContentWidth = Services.prefs.getIntPref("reader.content_width");
currentContentWidth = Math.max(
CONTENT_WIDTH_MIN,
Math.min(CONTENT_WIDTH_MAX, currentContentWidth)
);
this._displayContentWidth(currentContentWidth);
let plusButton = this._doc.querySelector(".content-width-plus-button");
let minusButton = this._doc.querySelector(".content-width-minus-button");
function updateControls() {
if (currentContentWidth === CONTENT_WIDTH_MIN) {
minusButton.setAttribute("disabled", true);
} else {
minusButton.removeAttribute("disabled");
}
if (currentContentWidth === CONTENT_WIDTH_MAX) {
plusButton.setAttribute("disabled", true);
} else {
plusButton.removeAttribute("disabled");
}
}
updateControls();
this._setContentWidth(currentContentWidth);
plusButton.addEventListener(
"click",
event => {
if (!event.isTrusted) {
return;
}
event.stopPropagation();
if (currentContentWidth >= CONTENT_WIDTH_MAX) {
return;
}
currentContentWidth++;
updateControls();
this._setContentWidth(currentContentWidth);
},
true
);
minusButton.addEventListener(
"click",
event => {
if (!event.isTrusted) {
return;
}
event.stopPropagation();
if (currentContentWidth <= CONTENT_WIDTH_MIN) {
return;
}
currentContentWidth--;
updateControls();
this._setContentWidth(currentContentWidth);
},
true
);
},
_setLineHeight(newLineHeight) {
this._displayLineHeight(newLineHeight);
let height = 1 + 0.2 * (newLineHeight - 1) + "em";
this._containerElement.style.setProperty("--line-height", height);
return lazy.AsyncPrefs.set("reader.line_height", newLineHeight);
},
_displayLineHeight(currentLineHeight) {
let lineHeightValue = this._doc.querySelector(".line-height-value");
lineHeightValue.textContent = currentLineHeight;
},
_setupLineHeightButtons() {
const LINE_HEIGHT_MIN = 1;
const LINE_HEIGHT_MAX = 9;
let currentLineHeight = Services.prefs.getIntPref("reader.line_height");
currentLineHeight = Math.max(
LINE_HEIGHT_MIN,
Math.min(LINE_HEIGHT_MAX, currentLineHeight)
);
this._displayLineHeight(currentLineHeight);
let plusButton = this._doc.querySelector(".line-height-plus-button");
let minusButton = this._doc.querySelector(".line-height-minus-button");
function updateControls() {
if (currentLineHeight === LINE_HEIGHT_MIN) {
minusButton.setAttribute("disabled", true);
} else {
minusButton.removeAttribute("disabled");
}
if (currentLineHeight === LINE_HEIGHT_MAX) {
plusButton.setAttribute("disabled", true);
} else {
plusButton.removeAttribute("disabled");
}
}
updateControls();
this._setLineHeight(currentLineHeight);
plusButton.addEventListener(
"click",
event => {
if (!event.isTrusted) {
return;
}
event.stopPropagation();
if (currentLineHeight >= LINE_HEIGHT_MAX) {
return;
}
currentLineHeight++;
updateControls();
this._setLineHeight(currentLineHeight);
},
true
);
minusButton.addEventListener(
"click",
event => {
if (!event.isTrusted) {
return;
}
event.stopPropagation();
if (currentLineHeight <= LINE_HEIGHT_MIN) {
return;
}
currentLineHeight--;
updateControls();
this._setLineHeight(currentLineHeight);
},
true
);
},
_setupSelector(id, options, initialValue, callback, l10nIds) {
let doc = this._doc;
let selector = doc.getElementById(`${id}-selector`);
@@ -1098,8 +855,7 @@ AboutReader.prototype = {
sliderContainer.appendChild(slider);
},
// Rename this function to setContentWidth when the old menu is retired.
_setContentWidthSlider(newContentWidth) {
_setContentWidth(newContentWidth) {
// We map the slider range [1-9] to 20-60em.
let width = 20 + 5 * (newContentWidth - 1) + "em";
this._doc.body.style.setProperty("--content-width", width);
@@ -1206,7 +962,7 @@ AboutReader.prototype = {
let contentWidth = doc.querySelector("#content-width-slider moz-slider");
contentWidth.setAttribute("value", initial.contentWidth);
this._setContentWidthSlider(initial.contentWidth);
this._setContentWidth(initial.contentWidth);
let lineSpacing = doc.querySelector("#line-spacing-slider moz-slider");
lineSpacing.setAttribute("value", initial.lineSpacing);
@@ -1302,14 +1058,10 @@ AboutReader.prototype = {
// Pref values include "auto", "dark", "light", "sepia",
// "gray", "contrast", and "custom"
_setColorSchemePref(colorSchemePref, fromInputEvent = false) {
// The input event for the last selected segmented button is fired
if (this._colorScheme == "custom" && fromInputEvent) {
// The input event for the last selected radio button is fired
// upon loading a reader article in the same session. To prevent it
// from overwriting custom colors, we return false.
const colorsMenuEnabled = Services.prefs.getBoolPref(
"reader.colors_menu.enabled",
false
);
if (colorsMenuEnabled && this._colorScheme == "custom" && fromInputEvent) {
lastSelectedTheme = colorSchemePref;
return false;
}
@@ -1319,23 +1071,162 @@ AboutReader.prototype = {
return true;
},
_setFontType(newFontType) {
if (this._fontType === newFontType) {
return false;
_handleColorsTabClick(option) {
let doc = this._doc;
let deck = doc.querySelector("named-deck");
if (option == deck.getAttribute("selected-view")) {
return;
}
let bodyClasses = this._doc.body.classList;
if (option == "customtheme") {
this._setColorSchemePref("custom");
lazy.AsyncPrefs.set("reader.color_scheme", "custom");
if (this._fontType) {
bodyClasses.remove(this._fontType);
// Store the last selected preset theme button.
const colorSchemePresets = doc.querySelector(".color-scheme-buttons");
const labels = colorSchemePresets.querySelectorAll("label");
labels.forEach(label => {
if (label.hasAttribute("checked")) {
lastSelectedTheme = label.className.split("-")[0];
}
});
} else if (option == "fxtheme") {
this._setColorSchemePref(lastSelectedTheme);
lazy.AsyncPrefs.set("reader.color_scheme", lastSelectedTheme);
// set the last selected button to checked.
const colorSchemePresets = doc.querySelector(".color-scheme-buttons");
const labels = colorSchemePresets.querySelectorAll("label");
labels.forEach(label => {
if (label.className == `${lastSelectedTheme}-button`) {
label.setAttribute("checked", "true");
label.previousElementSibling.setAttribute("checked", "true");
}
});
}
},
_setupColorsTabs(options, callback) {
let doc = this._doc;
let colorScheme = Services.prefs.getCharPref("reader.color_scheme");
for (let option of options) {
let tabButton = doc.getElementById(`tabs-deck-button-${option}`);
// Open custom theme tab if color scheme is set to custom.
if (option == "customtheme" && colorScheme == "custom") {
tabButton.click();
}
tabButton.addEventListener(
"click",
function (aEvent) {
if (!aEvent.isTrusted) {
return;
}
this._fontType = newFontType;
bodyClasses.add(this._fontType);
callback(option);
},
true
);
}
},
lazy.AsyncPrefs.set("reader.font_type", this._fontType);
_setupColorInput(prop) {
let doc = this._doc;
let input = doc.createElement("color-input");
input.setAttribute("prop-name", prop);
let labelL10nId = `about-reader-custom-colors-${prop}`;
input.setAttribute("data-l10n-id", labelL10nId);
return true;
let pref = `reader.custom_colors.${prop}`;
let customColor = Services.prefs.getStringPref(pref, "");
// Set the swatch color from prefs if one has been set.
if (customColor) {
input.setAttribute("color", customColor);
} else {
let defaultColor = DEFAULT_COLORS[prop];
input.setAttribute("color", defaultColor);
}
// Attach event listener to update the pref and page colors on input.
input.addEventListener("color-picked", e => {
const cssPropToUpdate = `--custom-theme-${prop}`;
this._doc.body.style.setProperty(cssPropToUpdate, e.detail);
const prefToUpdate = `reader.custom_colors.${prop}`;
lazy.AsyncPrefs.set(prefToUpdate, e.detail);
});
return input;
},
_setupCustomColors(options, id) {
let doc = this._doc;
const list = doc.getElementsByClassName(id)[0];
for (let option of options) {
let listItem = doc.createElement("li");
let colorInput = this._setupColorInput(option);
listItem.appendChild(colorInput);
list.appendChild(listItem);
}
},
_resetCustomColors() {
// Need to reset prefs, page colors, and color inputs.
const colorInputs = this._doc.querySelectorAll("color-input");
colorInputs.forEach(input => {
let property = input.getAttribute("prop-name");
let pref = `reader.custom_colors.${property}`;
lazy.AsyncPrefs.set(pref, "");
// Set css props to empty strings so they use fallback value.
let cssProp = `--custom-theme-${property}`;
this._doc.body.style.setProperty(cssProp, "");
let defaultColor = DEFAULT_COLORS[property];
input.setAttribute("color", defaultColor);
});
},
_handleThemeFocus() {
// Retain focus inside the menu panel.
let doc = this._doc;
let themeButtons = doc.querySelector(".color-scheme-buttons");
let defaultThemeFirstFocusable = doc.querySelector(
"#tabs-deck-button-fxtheme"
);
let themeResetButton = doc.querySelector(".custom-colors-reset-button");
let customThemeFirstFocusable = doc.querySelector(
"#tabs-deck-button-customtheme"
);
themeButtons.addEventListener("keydown", e => {
if (e.key === "Tab" && !e.shiftKey) {
e.preventDefault();
defaultThemeFirstFocusable.focus();
}
});
themeResetButton.addEventListener("keydown", e => {
if (e.key === "Tab" && !e.shiftKey) {
e.preventDefault();
customThemeFirstFocusable.focus();
}
});
defaultThemeFirstFocusable.addEventListener("keydown", e => {
if (e.key === "Tab" && e.shiftKey) {
e.preventDefault();
let themeLabels = themeButtons.getElementsByTagName("label");
for (const label of themeLabels) {
if (label.hasAttribute("checked")) {
doc.querySelector(`.${label.className}`).focus();
}
}
}
});
customThemeFirstFocusable.addEventListener("keydown", e => {
if (e.key === "Tab" && e.shiftKey) {
e.preventDefault();
themeResetButton.focus();
}
});
},
async _loadArticle(docContentType = "document") {
@@ -1702,169 +1593,6 @@ AboutReader.prototype = {
);
},
_handleColorsTabClick(option) {
let doc = this._doc;
let deck = doc.querySelector("named-deck");
if (option == deck.getAttribute("selected-view")) {
return;
}
if (option == "customtheme") {
this._setColorSchemePref("custom");
lazy.AsyncPrefs.set("reader.color_scheme", "custom");
// Store the last selected preset theme button.
const colorSchemePresets = doc.querySelector(
".colors-menu-color-scheme-buttons"
);
const labels = colorSchemePresets.querySelectorAll("label");
labels.forEach(label => {
if (label.hasAttribute("checked")) {
lastSelectedTheme = label.className.split("-")[0];
}
});
} else if (option == "fxtheme") {
this._setColorSchemePref(lastSelectedTheme);
lazy.AsyncPrefs.set("reader.color_scheme", lastSelectedTheme);
// set the last selected button to checked.
const colorSchemePresets = doc.querySelector(
".colors-menu-color-scheme-buttons"
);
const labels = colorSchemePresets.querySelectorAll("label");
labels.forEach(label => {
if (label.className == `${lastSelectedTheme}-button`) {
label.setAttribute("checked", "true");
label.previousElementSibling.setAttribute("checked", "true");
}
});
}
},
_setupColorsTabs(options, callback) {
let doc = this._doc;
let colorScheme = Services.prefs.getCharPref("reader.color_scheme");
for (let option of options) {
let tabButton = doc.getElementById(`tabs-deck-button-${option}`);
// Open custom theme tab if color scheme is set to custom.
if (option == "customtheme" && colorScheme == "custom") {
tabButton.click();
}
tabButton.addEventListener(
"click",
function (aEvent) {
if (!aEvent.isTrusted) {
return;
}
callback(option);
},
true
);
}
},
_setupColorInput(prop) {
let doc = this._doc;
let input = doc.createElement("color-input");
input.setAttribute("prop-name", prop);
let labelL10nId = `about-reader-custom-colors-${prop}`;
input.setAttribute("data-l10n-id", labelL10nId);
input.setAttribute("data-telemetry-id", `custom-color-picker-${prop}`);
let pref = `reader.custom_colors.${prop}`;
let customColor = Services.prefs.getStringPref(pref, "");
// Set the swatch color from prefs if one has been set.
if (customColor) {
input.setAttribute("color", customColor);
} else {
let defaultColor = DEFAULT_COLORS[prop];
input.setAttribute("color", defaultColor);
}
// Attach event listener to update the pref and page colors on input.
input.addEventListener("color-picked", e => {
const cssPropToUpdate = `--custom-theme-${prop}`;
this._doc.body.style.setProperty(cssPropToUpdate, e.detail);
const prefToUpdate = `reader.custom_colors.${prop}`;
lazy.AsyncPrefs.set(prefToUpdate, e.detail);
});
return input;
},
_setupCustomColors(options, id) {
let doc = this._doc;
const list = doc.getElementsByClassName(id)[0];
for (let option of options) {
let listItem = doc.createElement("li");
let colorInput = this._setupColorInput(option);
listItem.appendChild(colorInput);
list.appendChild(listItem);
}
},
_resetCustomColors() {
// Need to reset prefs, page colors, and color inputs.
const colorInputs = this._doc.querySelectorAll("color-input");
colorInputs.forEach(input => {
let property = input.getAttribute("prop-name");
let pref = `reader.custom_colors.${property}`;
lazy.AsyncPrefs.set(pref, "");
// Set css props to empty strings so they use fallback value.
let cssProp = `--custom-theme-${property}`;
this._doc.body.style.setProperty(cssProp, "");
let defaultColor = DEFAULT_COLORS[property];
input.setAttribute("color", defaultColor);
});
},
_handleThemeFocus() {
// Retain focus inside the menu panel.
let doc = this._doc;
let themeButtons = doc.querySelector(".colors-menu-color-scheme-buttons");
let defaultThemeFirstFocusable = doc.querySelector(
"#tabs-deck-button-fxtheme"
);
let themeResetButton = doc.querySelector(".custom-colors-reset-button");
let customThemeFirstFocusable = doc.querySelector(
"#tabs-deck-button-customtheme"
);
themeButtons.addEventListener("keydown", e => {
if (e.key === "Tab" && !e.shiftKey) {
e.preventDefault();
defaultThemeFirstFocusable.focus();
}
});
themeResetButton.addEventListener("keydown", e => {
if (e.key === "Tab" && !e.shiftKey) {
e.preventDefault();
customThemeFirstFocusable.focus();
}
});
defaultThemeFirstFocusable.addEventListener("keydown", e => {
if (e.key === "Tab" && e.shiftKey) {
e.preventDefault();
let themeLabels = themeButtons.getElementsByTagName("label");
for (const label of themeLabels) {
if (label.hasAttribute("checked")) {
doc.querySelector(`.${label.className}`).focus();
}
}
}
});
customThemeFirstFocusable.addEventListener("keydown", e => {
if (e.key === "Tab" && e.shiftKey) {
e.preventDefault();
themeResetButton.focus();
}
});
},
_toggleDropdownClicked(event) {
let dropdown = event.target.closest(".dropdown");

View File

@@ -54,14 +54,10 @@
data-l10n-id="about-reader-toolbar-close"
></span>
</button>
<ul
class="dropdown improved-style-dropdown"
id="improved-text-menu"
hidden="true"
>
<ul class="dropdown text-layout-dropdown">
<li>
<button
class="dropdown-toggle toolbar-button improved-style-button"
class="dropdown-toggle toolbar-button text-layout-button"
aria-labelledby="toolbar-text-layout-controls"
data-telemetry-id="reader-text-layout-controls"
>
@@ -155,67 +151,7 @@
</details>
</li>
</ul>
<ul class="dropdown style-dropdown" id="regular-text-menu">
<li>
<button
class="dropdown-toggle toolbar-button style-button"
aria-labelledby="toolbar-type-controls"
data-telemetry-id="reader-type-controls"
>
<span
class="hover-label"
id="toolbar-type-controls"
data-l10n-id="about-reader-toolbar-type-controls"
></span>
</button>
</li>
<li class="dropdown-popup">
<div class="font-type-buttons radiorow"></div>
<div class="font-size-buttons buttonrow">
<button
class="minus-button"
data-l10n-id="about-reader-toolbar-minus"
></button>
<span class="font-size-value"></span>
<button
class="plus-button"
data-l10n-id="about-reader-toolbar-plus"
></button>
</div>
<div class="content-width-buttons buttonrow">
<button
class="content-width-minus-button"
data-l10n-id="about-reader-toolbar-contentwidthminus"
></button>
<span class="content-width-value"></span>
<button
class="content-width-plus-button"
data-l10n-id="about-reader-toolbar-contentwidthplus"
></button>
</div>
<div class="line-height-buttons buttonrow">
<button
class="line-height-minus-button"
data-l10n-id="about-reader-toolbar-lineheightminus"
></button>
<span class="line-height-value"></span>
<button
class="line-height-plus-button"
data-l10n-id="about-reader-toolbar-lineheightplus"
></button>
</div>
<div
class="color-scheme-buttons radiorow"
id="regular-color-scheme"
hidden="false"
></div>
</li>
</ul>
<ul
class="dropdown colors-dropdown"
id="custom-colors-color-scheme"
hidden="true"
>
<ul class="dropdown colors-dropdown">
<li>
<button
class="dropdown-toggle toolbar-button colors-button"
@@ -251,10 +187,7 @@
></button>
</button-group>
<named-deck id="tabs-deck" is-tabbed>
<div
name="fxtheme"
class="colors-menu-color-scheme-buttons radiorow"
></div>
<div name="fxtheme" class="color-scheme-buttons radiorow"></div>
<div name="customtheme">
<ul class="custom-colors-selection"></ul>
<button

View File

@@ -68,7 +68,6 @@ add_task(async function () {
async function testColorsFocus() {
// Set the theme selection to auto.
Services.prefs.setBoolPref("reader.colors_menu.enabled", true);
Services.prefs.setCharPref("reader.color_scheme", "auto");
// Open a browser tab, enter reader mode, and test if focus stays

View File

@@ -11,7 +11,6 @@ const TEST_PATH = getRootDirectory(gTestPath).replace(
async function testCustomColors(aPref, color) {
// Set the theme selection to custom.
Services.prefs.setBoolPref("reader.colors_menu.enabled", true);
Services.prefs.setCharPref("reader.color_scheme", "custom");
// Set the custom pref to the color value.

View File

@@ -106,9 +106,9 @@ add_task(async function () {
await SpecialPowers.spawn(browser, [], async function () {
let doc = content.document;
let dropdown = doc.querySelector(".improved-style-dropdown");
let dropdown = doc.querySelector(".text-layout-dropdown");
doc.querySelector(".improved-style-button").click();
doc.querySelector(".text-layout-button").click();
ok(dropdown.classList.contains("open"), "dropdown is open");
// hover outside the dropdown and scroll
@@ -122,9 +122,7 @@ add_task(async function () {
});
await scrollEventPromise;
await SpecialPowers.spawn(browser, [], async function () {
let dropdown = content.document.querySelector(
".improved-style-dropdown"
);
let dropdown = content.document.querySelector(".text-layout-dropdown");
ok(!dropdown.classList.contains("open"), "dropdown is closed");
});
@@ -136,10 +134,10 @@ add_task(async function () {
await SpecialPowers.spawn(browser, [], async function () {
let doc = content.document;
let dropdown = doc.querySelector(".improved-style-dropdown");
let dropdown = doc.querySelector(".text-layout-dropdown");
// reopen the dropdown
doc.querySelector(".improved-style-button").click();
doc.querySelector(".text-layout-button").click();
ok(dropdown.classList.contains("open"), "dropdown is open");
// hover over the dropdown and scroll
@@ -155,9 +153,7 @@ add_task(async function () {
});
await scrollEventPromise;
await SpecialPowers.spawn(browser, [], async function () {
let dropdown = content.document.querySelector(
".improved-style-dropdown"
);
let dropdown = content.document.querySelector(".text-layout-dropdown");
ok(dropdown.classList.contains("open"), "dropdown remains open");
});
}

View File

@@ -24,9 +24,6 @@ const defaultValues = {
* the document layout correctly.
*/
async function testTextLayout(aPref, value, cssProp, cssValue) {
// Enable the improved text and layout menu.
Services.prefs.setBoolPref("reader.improved_text_menu.enabled", true);
// Set the pref to the custom value.
const valueType = typeof value;
if (valueType == "number") {
@@ -75,9 +72,6 @@ async function testTextLayout(aPref, value, cssProp, cssValue) {
* Test that the reset button restores all layout options to defaults.
*/
async function testTextLayoutReset() {
// Enable the improved text and layout menu.
Services.prefs.setBoolPref("reader.improved_text_menu.enabled", true);
// Set all prefs to non-default values.
Services.prefs.setIntPref(`reader.font_size`, 15);
Services.prefs.setCharPref(`reader.font_type`, "serif");
@@ -134,9 +128,6 @@ async function testTextLayoutReset() {
* Test that the focus stays within the text and layout menu.
*/
async function testTextLayoutFocus() {
// Enable the improved text and layout menu.
Services.prefs.setBoolPref("reader.improved_text_menu.enabled", true);
// Open a browser tab, enter reader mode, and test if the focus stays
// within the menu.
await BrowserTestUtils.withNewTab(
@@ -153,7 +144,7 @@ async function testTextLayoutFocus() {
await SpecialPowers.spawn(browser, [], () => {
let doc = content.document;
doc.querySelector(".improved-style-button").click();
doc.querySelector(".text-layout-button").click();
let firstFocusableElement = doc.querySelector(
".text-size-minus-button"

View File

@@ -22,7 +22,6 @@ next-label = Forward (%S)
speed = Speed
slow-speed-label = Slow down narration
fast-speed-label = Speed up narration
selectvoicelabel = Voice:
select-voice-header = Voice
# Default voice is determined by the language of the document.
defaultvoice = Default

View File

@@ -29,21 +29,6 @@ about-reader-estimated-read-time =
*[other] { $range } minutes
}
## These are used as tooltips in Type Control
about-reader-toolbar-minus =
.title = Decrease font size
about-reader-toolbar-plus =
.title = Increase font size
about-reader-toolbar-contentwidthminus =
.title = Decrease Content Width
about-reader-toolbar-contentwidthplus =
.title = Increase Content Width
about-reader-toolbar-lineheightminus =
.title = Decrease Line Height
about-reader-toolbar-lineheightplus =
.title = Increase Line Height
## These are the styles of typeface that are options in the reader view controls.
about-reader-font-type-serif = Serif
@@ -53,7 +38,6 @@ about-reader-font-type-monospace = Monospace
## Reader View toolbar buttons
about-reader-toolbar-close = Close Reader View
about-reader-toolbar-type-controls = Type controls
about-reader-toolbar-text-layout-controls = Text and layout
about-reader-toolbar-theme-controls = Theme
about-reader-toolbar-savetopocket = Save to { -pocket-brand-name }
@@ -84,11 +68,16 @@ about-reader-custom-colors-selection-highlight = Highlighter for read aloud
about-reader-reset-button = Reset defaults
## Reader View improved text and layout menu
## Reader View text and layout menu
about-reader-text-header = Text
about-reader-text-size-label = Text size
about-reader-toolbar-minus =
.title = Decrease font size
about-reader-toolbar-plus =
.title = Increase font size
about-reader-font-type-selector-label = Font
about-reader-font-weight-selector-label = Font weight

View File

@@ -58,8 +58,6 @@ body {
--popup-button-border: rgba(0, 0, 0, 0.2);
--selected-background: rgba(0, 97, 224, 0.3);
--outline-focus-color: var(--primary-color);
--font-value-background: rgb(240, 240, 244);
--font-value-border: var(--grey-30);
--icon-fill: rgb(91, 91, 102);
--icon-disabled-fill: rgba(91, 91, 102, 0.4);
--text-selected-background: var(--selected-background);
@@ -107,8 +105,6 @@ body.contrast {
--popup-button-border: rgba(255, 255, 255, 0.2);
--popup-line: rgba(249, 249, 250, 0.1);
--popup-button-background: rgb(43, 42, 51);
--font-value-background: rgba(249, 249, 250, 0.15);
--font-value-border: #656468;
--icon-disabled-fill: rgba(251, 251, 254, 0.4);
--link-selected-foreground: #fff;
--visited-link-foreground: #e675fd;
@@ -187,8 +183,6 @@ body.hcm {
--link-color-hover: SelectedItem;
--selected-background: Canvas;
--outline-focus-color: CanvasText;
--font-value-background: Canvas;
--font-value-border: CanvasText;
--icon-fill: ButtonText;
--icon-disabled-fill: GrayText;
--text-selected-background: SelectedItem;
@@ -253,31 +247,6 @@ blockquote {
border-inline-start: 2px solid var(--main-foreground) !important;
}
.color-scheme-buttons {
.light-button,
.auto-button {
color: var(--light-theme-foreground);
background-color: var(--light-theme-background);
}
@media (prefers-color-scheme: dark) {
.auto-button {
color: var(--dark-theme-foreground);
background-color: var(--dark-theme-background);
}
}
.dark-button {
color: var(--dark-theme-foreground);
background-color: var(--dark-theme-background);
}
.sepia-button {
color: #5b4636;
background-color: #f4ecd8;
}
}
/* Loading/error message */
.reader-message {
@@ -550,8 +519,6 @@ button:disabled {
visibility: visible;
}
/* Font style popup */
.radio-button {
/* We visually hide these, but we keep them around so they can be focused
* and changed by interacting with them via the label, or the keyboard, or
@@ -569,28 +536,7 @@ button:disabled {
justify-content: center;
}
.content-width-value,
.font-size-value,
.line-height-value {
box-sizing: border-box;
width: 36px;
height: 20px;
line-height: 18px;
display: flex;
justify-content: center;
align-content: center;
margin: auto;
border-radius: 10px;
border: 1px solid var(--font-value-border);
color: var(--popup-button-foreground);
background-color: var(--font-value-background);
}
.buttonrow > button {
border: 0;
height: 60px;
width: 90px;
background-color: transparent;
background-repeat: no-repeat;
background-position: center;
fill: var(--popup-button-foreground);
@@ -610,11 +556,6 @@ button:disabled {
outline-offset: -2px;
}
.style-dropdown .radiorow:not(:last-child),
.style-dropdown .buttonrow:not(:last-child) {
border-bottom: 1px solid var(--popup-line);
}
.radiorow > label {
position: relative;
box-sizing: border-box;
@@ -636,56 +577,6 @@ button:disabled {
z-index: 1;
}
.font-type-buttons > label {
height: 64px;
width: 105px;
/* Slightly more space between these items. */
margin: 10px;
/* Center the Sans-serif / Serif labels */
text-align: center;
background-size: 63px 39px;
background-repeat: no-repeat;
background-position: center 18px;
background-color: var(--popup-button-background);
color: var(--popup-button-foreground);
fill: currentColor;
-moz-context-properties: fill;
/* This mostly matches baselines, but because of differences in font
* baselines between serif and sans-serif, this isn't always enough. */
line-height: 1;
padding-top: 2px;
border-radius: 2px;
}
.font-type-buttons {
> label:first-of-type {
margin-inline-start: var(--space-large);
}
> label:last-of-type {
margin-inline-end: var(--space-large);
}
}
.font-type-buttons > label[checked] {
background-color: var(--selected-background);
}
.sans-serif-button {
font-family: sans-serif;
background-image: url("chrome://global/skin/reader/RM-Sans-Serif.svg");
}
/* Tweak padding to match the baseline on mac */
:root[platform=macosx] .sans-serif-button {
padding-top: 3px;
}
.serif-button {
font-family: serif;
background-image: url("chrome://global/skin/reader/RM-Serif.svg");
}
body.hcm .color-scheme-buttons {
/* Disallow selecting themes when HCM is on. */
display: none;
@@ -930,7 +821,7 @@ label[for="text-alignment-buttons"] {
}
}
/* Separate colors menu popup */
/* Colors menu popup */
#color-controls {
padding-block: var(--space-small);
@@ -975,12 +866,12 @@ div[name="customtheme"] {
color: var(--popup-button-foreground);
}
.colors-menu-color-scheme-buttons {
.color-scheme-buttons {
flex-wrap: wrap;
padding-block: var(--space-xsmall) var(--space-small);
}
.colors-menu-color-scheme-buttons > label {
.color-scheme-buttons > label {
height: 48px;
width: calc(50% - 21px);
font-size: 15px;
@@ -994,7 +885,7 @@ div[name="customtheme"] {
margin: var(--space-xsmall);
}
.colors-menu-color-scheme-buttons > label:before {
.color-scheme-buttons > label:before {
content: "";
display: inline-block;
width: 24px;
@@ -1004,7 +895,7 @@ div[name="customtheme"] {
margin-inline: var(--space-medium);
}
.colors-menu-color-scheme-buttons {
.color-scheme-buttons {
.auto-button:before {
background: linear-gradient(to right, var(--light-theme-background) 50%, var(--dark-theme-background) 50%);;
}
@@ -1059,11 +950,7 @@ div[name="customtheme"] {
background-image: url("chrome://global/skin/icons/close.svg");
}
.style-button {
background-image: url("chrome://global/skin/reader/RM-Type-Controls-24x24.svg");
}
.improved-style-button {
.text-layout-button {
background-image: url("chrome://global/skin/reader/RM-Type-Controls-24x24.svg");
}
@@ -1071,42 +958,6 @@ div[name="customtheme"] {
background-image: url("chrome://mozapps/skin/extensions/category-themes.svg");
}
.minus-button {
background-size: 18px 18px;
background-image: url("chrome://global/skin/reader/RM-Minus-24x24.svg");
}
.plus-button {
background-size: 18px 18px;
background-image: url("chrome://global/skin/reader/RM-Plus-24x24.svg");
}
.content-width-minus-button {
background-size: 42px 16px;
background-image: url("chrome://global/skin/reader/RM-Content-Width-Minus-42x16.svg");
}
.content-width-plus-button {
background-size: 44px 16px;
background-image: url("chrome://global/skin/reader/RM-Content-Width-Plus-44x16.svg");
}
.line-height-minus-button {
background-size: 34px 14px;
background-image: url("chrome://global/skin/reader/RM-Line-Height-Minus-38x14.svg");
}
.line-height-plus-button {
background-size: 34px 24px;
background-image: url("chrome://global/skin/reader/RM-Line-Height-Plus-38x24.svg");
}
/* Mirror the line height buttons if the article is RTL. */
.reader-controls[articledir="rtl"] .line-height-minus-button,
.reader-controls[articledir="rtl"] .line-height-plus-button {
transform: scaleX(-1);
}
@media print {
.toolbar {
display: none !important;

View File

@@ -137,29 +137,15 @@
skin/classic/global/media/picture-in-picture-closed.svg (../../shared/media/picture-in-picture-closed.svg)
skin/classic/global/icons/minus.svg (../../shared/icons/minus.svg)
skin/classic/global/narrate.css (../../shared/narrate.css)
skin/classic/global/narrate-improved.css (../../shared/narrate-improved.css)
skin/classic/global/narrate/arrow.svg (../../shared/narrate/arrow.svg)
skin/classic/global/narrate/back.svg (../../shared/narrate/back.svg)
skin/classic/global/narrate/skip-backward-20.svg (../../shared/narrate/skip-backward-20.svg)
skin/classic/global/narrate/skip-forward-20.svg (../../shared/narrate/skip-forward-20.svg)
skin/classic/global/narrate/fast.svg (../../shared/narrate/fast.svg)
skin/classic/global/narrate/forward.svg (../../shared/narrate/forward.svg)
skin/classic/global/narrate/slow.svg (../../shared/narrate/slow.svg)
skin/classic/global/narrate/start.svg (../../shared/narrate/start.svg)
skin/classic/global/narrate/stop.svg (../../shared/narrate/stop.svg)
skin/classic/global/narrate/headphone.svg (../../shared/narrate/headphone.svg)
skin/classic/global/narrate/headphone-active.svg (../../shared/narrate/headphone-active.svg)
skin/classic/global/pictureinpicture/player.css (../../shared/pictureinpicture/player.css)
skin/classic/global/pictureinpicture/texttracks.css (../../shared/pictureinpicture/texttracks.css)
skin/classic/global/reader/RM-Sans-Serif.svg (../../shared/reader/RM-Sans-Serif.svg)
skin/classic/global/reader/RM-Serif.svg (../../shared/reader/RM-Serif.svg)
skin/classic/global/reader/RM-Minus-24x24.svg (../../shared/reader/RM-Minus-24x24.svg)
skin/classic/global/reader/RM-Plus-24x24.svg (../../shared/reader/RM-Plus-24x24.svg)
skin/classic/global/reader/RM-Type-Controls-24x24.svg (../../shared/reader/RM-Type-Controls-24x24.svg)
skin/classic/global/reader/RM-Content-Width-Minus-42x16.svg (../../shared/reader/RM-Content-Width-Minus-42x16.svg)
skin/classic/global/reader/RM-Content-Width-Plus-44x16.svg (../../shared/reader/RM-Content-Width-Plus-44x16.svg)
skin/classic/global/reader/RM-Line-Height-Minus-38x14.svg (../../shared/reader/RM-Line-Height-Minus-38x14.svg)
skin/classic/global/reader/RM-Line-Height-Plus-38x24.svg (../../shared/reader/RM-Line-Height-Plus-38x24.svg)
skin/classic/global/reader/align-left-20.svg (../../shared/reader/align-left-20.svg)
skin/classic/global/reader/align-center-20.svg (../../shared/reader/align-center-20.svg)
skin/classic/global/reader/align-right-20.svg (../../shared/reader/align-right-20.svg)

View File

@@ -1,281 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* Avoid adding ID selector rules in this style sheet, since they could
* inadvertently match elements in the article content. */
body {
--narrate-word-highlight-color: #ffe087;
--narrating-paragraph-background-color: #ffc;
}
body.sepia {
--narrate-word-highlight-color: #bdb5a5;
--narrating-paragraph-background-color: #e0d7c5;
}
body.dark,
body.contrast {
--narrate-word-highlight-color: #6f6f6f;
--narrating-paragraph-background-color: #242424;
}
body.custom {
--narrating-paragraph-background-color: var(--custom-theme-selection-highlight);
}
body.hcm {
--narrate-word-highlight-color: SelectedItem;
--narrating-paragraph-background-color: Canvas;
}
.narrating {
position: relative;
z-index: 1;
background-color: var(--narrating-paragraph-background-color);
}
.narrate-word-highlight {
position: absolute;
display: none;
transform: translate(-50%, calc(-50% - 2px));
z-index: -1;
border-bottom: 7px solid var(--narrate-word-highlight-color);
transition: left 0.1s ease, width 0.1s ease;
}
body.hcm .narrate-word-highlight {
/* Shift the word highlight a bit downwards to not cover the bottom part of characters.
* The z-index above is meant to have the highlight appear below the text,
* but that's not best practice in HCM so we do this instead. */
transform: translate(-50%, calc(-50% + 2px));
border-bottom-width: 3px;
}
.narrating > .narrate-word-highlight {
display: inline-block;
}
.narrate-word-highlight.newline {
transition: none;
}
.narrate-toggle {
background-image: url("chrome://global/skin/narrate/headphone.svg");
.speaking & {
/* This shows with an animation. */
background-image: url("chrome://global/skin/narrate/headphone-active.svg");
fill: var(--toolbar-button-foreground-active);
}
body.hcm .speaking & {
background-color: var(--toolbar-button-background-active);
border-color: var(--toolbar-button-border-active);
}
body.hcm .speaking:not(.open) &:hover {
background-color: var(--toolbar-button-background-hover);
border-color: var(--toolbar-button-border-hover);
fill: var(--toolbar-button-foreground-hover);
}
}
.narrate-dropdown > .dropdown-popup {
padding: var(--space-small) var(--space-large);
button:enabled:hover {
background-color: var(--popup-button-background-hover);
color: var(--popup-button-foreground-hover);
fill: var(--popup-button-foreground-hover);
body.hcm & {
border-color: SelectedItem;
}
}
button:enabled:hover:active {
background-color: var(--popup-button-background-active);
body.hcm & {
border-color: ButtonText;
}
}
button:enabled:focus-visible {
outline: 2px solid var(--outline-focus-color);
outline-offset: -2px;
}
}
.narrate-row {
display: flex;
align-items: center;
padding-block: var(--space-small);
&:not(.narrate-voices) {
direction: ltr;
}
}
/* Control buttons */
.narrate-control {
gap: var(--space-xxsmall);
button {
display: flex;
flex: 1;
min-height: 36px;
background-repeat: no-repeat;
background-position: center;
background-size: 20px 20px;
background-color: var(--popup-button-background);
color: var(--popup-button-foreground);
fill: currentColor;
-moz-context-properties: fill;
border: none;
&:first-of-type {
border-start-start-radius: var(--border-radius-small);
border-end-start-radius: var(--border-radius-small);
}
&:last-of-type {
border-start-end-radius: var(--border-radius-small);
border-end-end-radius: var(--border-radius-small);
}
&.narrate-skip-previous {
background-image: url("chrome://global/skin/narrate/skip-backward-20.svg");
}
&.narrate-skip-next {
background-image: url("chrome://global/skin/narrate/skip-forward-20.svg");
}
&.narrate-start-stop {
background-image: url("chrome://global/skin/media/play-fill.svg");
.narrate-dropdown.speaking & {
background-image: url("chrome://global/skin/media/pause-fill.svg");
}
}
body.hcm & {
border: 1px solid var(--popup-button-border);
&:disabled {
border-color: var(--icon-disabled-fill);
}
}
}
}
/* Rate control */
.narrate-rate-icon {
content: '';
width: 48px;
height: 40px;
background-position: center;
background-repeat: no-repeat;
background-size: 24px auto;
-moz-context-properties: fill;
fill: var(--popup-foreground);
&.slow {
background-image: url("chrome://global/skin/narrate/slow.svg");
}
&.fast {
background-image: url("chrome://global/skin/narrate/fast.svg");
}
}
.narrate-rate-input {
width: 200px;
}
/* Voice selection */
.voiceselect {
width: 100%;
> button.select-toggle,
> .options > button.option {
appearance: none;
width: 100%;
min-height: 36px;
border: 1px solid transparent;
color: var(--popup-button-foreground);
font-size: 15px;
body.hcm & {
border-color: var(--popup-button-border);
}
}
> button.select-toggle {
display: flex;
align-items: center;
padding-inline: var(--space-medium);
border-radius: var(--border-radius-small);
background-color: var(--popup-button-background);
font-weight: var(--font-weight-bold);
-moz-context-properties: fill;
fill: currentColor;
.current-voice {
display: flex;
width: 100%;
padding-inline: var(--space-small);
}
}
> button.select-toggle::before,
> button.select-toggle::after {
content: "";
width: 24px;
height: var(--icon-size-default);
background-repeat: no-repeat;
background-size: var(--icon-size-default) auto;
}
> button.select-toggle::before {
background-image: url("chrome://global/skin/media/audio.svg");
}
> button.select-toggle::after {
background-image: url("chrome://global/skin/icons/arrow-down.svg");
}
&.open > button.select-toggle::after {
background-image: url("chrome://global/skin/icons/arrow-up.svg");
}
> .options {
display: none;
overflow-y: auto;
> button.option {
background-color: transparent;
text-align: start;
padding-inline-start: var(--space-medium);
}
> button.option::-moz-focus-inner {
outline: none;
border: 0;
}
&:not(.hovering) > button.option:hover:not(:focus) {
background-color: transparent;
}
}
&.open > .options {
display: block;
}
}

View File

@@ -6,7 +6,6 @@
* inadvertently match elements in the article content. */
body {
--current-voice: #7f7f7f;
--narrate-word-highlight-color: #ffe087;
--narrating-paragraph-background-color: #ffc;
}
@@ -18,7 +17,6 @@ body.sepia {
body.dark,
body.contrast {
--current-voice: #a09eac;
--narrate-word-highlight-color: #6f6f6f;
--narrating-paragraph-background-color: #242424;
}
@@ -28,7 +26,6 @@ body.custom {
}
body.hcm {
--current-voice: inherit;
--narrate-word-highlight-color: SelectedItem;
--narrating-paragraph-background-color: Canvas;
}
@@ -66,98 +63,119 @@ body.hcm .narrate-word-highlight {
.narrate-toggle {
background-image: url("chrome://global/skin/narrate/headphone.svg");
}
.speaking .narrate-toggle {
.speaking & {
/* This shows with an animation. */
background-image: url("chrome://global/skin/narrate/headphone-active.svg");
fill: var(--toolbar-button-foreground-active);
}
}
body.hcm .speaking .narrate-toggle {
body.hcm .speaking & {
background-color: var(--toolbar-button-background-active);
border-color: var(--toolbar-button-border-active);
}
}
body.hcm .speaking:not(.open) .narrate-toggle:hover {
body.hcm .speaking:not(.open) &:hover {
background-color: var(--toolbar-button-background-hover);
border-color: var(--toolbar-button-border-hover);
fill: var(--toolbar-button-foreground-hover);
}
}
.narrate-dropdown > .dropdown-popup button {
background-color: transparent;
fill: var(--popup-button-foreground);
}
.narrate-dropdown > .dropdown-popup {
padding: var(--space-small) var(--space-large);
.narrate-dropdown > .dropdown-popup button:enabled:hover {
button:enabled:hover {
background-color: var(--popup-button-background-hover);
color: var(--popup-button-foreground-hover);
fill: var(--popup-button-foreground-hover);
}
.narrate-dropdown > .dropdown-popup button:enabled:hover:active {
body.hcm & {
border-color: SelectedItem;
}
}
button:enabled:hover:active {
background-color: var(--popup-button-background-active);
}
.narrate-dropdown > .dropdown-popup button:enabled:focus-visible {
body.hcm & {
border-color: ButtonText;
}
}
button:enabled:focus-visible {
outline: 2px solid var(--outline-focus-color);
outline-offset: -2px;
}
}
.narrate-row {
display: flex;
align-items: center;
min-height: 40px;
box-sizing: border-box;
}
padding-block: var(--space-small);
.narrate-row:not(.narrate-voices) {
&:not(.narrate-voices) {
direction: ltr;
}
.narrate-row:not(:first-child) {
border-top: 1px solid var(--popup-line);
}
}
/* Control buttons */
.narrate-control > button {
background-size: 24px 24px;
.narrate-control {
gap: var(--space-xxsmall);
button {
display: flex;
flex: 1;
min-height: 36px;
background-repeat: no-repeat;
background-position: center center;
height: 64px;
width: 82px;
background-position: center;
background-size: 20px 20px;
background-color: var(--popup-button-background);
color: var(--popup-button-foreground);
fill: currentColor;
-moz-context-properties: fill;
border: none;
box-sizing: border-box;
}
.narrate-control > button:not(:first-child) {
border-inline-start: 1px solid var(--popup-line);
}
&:first-of-type {
border-start-start-radius: var(--border-radius-small);
border-end-start-radius: var(--border-radius-small);
}
.narrate-skip-previous {
border-top-left-radius: 3px;
background-image: url("chrome://global/skin/narrate/back.svg");
}
&:last-of-type {
border-start-end-radius: var(--border-radius-small);
border-end-end-radius: var(--border-radius-small);
}
.narrate-skip-next {
border-top-right-radius: 3px;
background-image: url("chrome://global/skin/narrate/forward.svg");
}
&.narrate-skip-previous {
background-image: url("chrome://global/skin/narrate/skip-backward-20.svg");
}
.narrate-start-stop {
background-image: url("chrome://global/skin/narrate/start.svg");
}
&.narrate-skip-next {
background-image: url("chrome://global/skin/narrate/skip-forward-20.svg");
}
.narrate-dropdown.speaking .narrate-start-stop {
background-image: url("chrome://global/skin/narrate/stop.svg");
&.narrate-start-stop {
background-image: url("chrome://global/skin/media/play-fill.svg");
.narrate-dropdown.speaking & {
background-image: url("chrome://global/skin/media/pause-fill.svg");
}
}
body.hcm & {
border: 1px solid var(--popup-button-border);
&:disabled {
border-color: var(--icon-disabled-fill);
}
}
}
}
/* Rate control */
.narrate-rate::before,
.narrate-rate::after {
.narrate-rate-icon {
content: '';
width: 48px;
height: 40px;
@@ -165,115 +183,99 @@ body.hcm .speaking:not(.open) .narrate-toggle:hover {
background-repeat: no-repeat;
background-size: 24px auto;
-moz-context-properties: fill;
fill: var(--popup-button-foreground);
}
fill: var(--popup-foreground);
.narrate-rate::before {
&.slow {
background-image: url("chrome://global/skin/narrate/slow.svg");
}
}
.narrate-rate::after {
&.fast {
background-image: url("chrome://global/skin/narrate/fast.svg");
}
}
.narrate-rate-input {
margin: 0 1px;
flex-grow: 1;
background-color: var(--popup-background);
border-radius: 2px;
width: 148px;
}
.narrate-rate-input:focus-visible {
outline: 2px solid var(--outline-focus-color);
outline-offset: 2px;
}
.narrate-rate-input::-moz-range-track {
background-color: var(--popup-button-foreground);
height: 2px;
}
.narrate-rate-input::-moz-range-progress {
background-color: var(--primary-color);
height: 2px;
}
.narrate-rate-input::-moz-range-thumb {
background-color: var(--popup-button-foreground);
height: 16px;
width: 16px;
border-radius: 8px;
border-width: 0;
}
.narrate-rate-input:active::-moz-range-thumb {
background-color: var(--primary-color);
width: 200px;
}
/* Voice selection */
.voiceselect {
width: 246px;
}
.voiceselect > button.select-toggle,
.voiceselect > .options > button.option {
appearance: none;
border: none;
width: 100%;
min-height: 40px;
}
.voiceselect > button.select-toggle::after {
content: '';
background-image: url("chrome://global/skin/narrate/arrow.svg");
background-position: center;
background-repeat: no-repeat;
background-size: 12px 12px;
display: inline-block;
width: 1.5em;
height: 1em;
vertical-align: middle;
}
.current-voice {
color: var(--current-voice);
}
.voiceselect .label {
> button.select-toggle,
> .options > button.option {
appearance: none;
width: 100%;
min-height: 36px;
border: 1px solid transparent;
color: var(--popup-button-foreground);
}
font-size: 15px;
.voiceselect > .options {
body.hcm & {
border-color: var(--popup-button-border);
}
}
> button.select-toggle {
display: flex;
align-items: center;
padding-inline: var(--space-medium);
border-radius: var(--border-radius-small);
background-color: var(--popup-button-background);
font-weight: var(--font-weight-bold);
-moz-context-properties: fill;
fill: currentColor;
.current-voice {
display: flex;
width: 100%;
padding-inline: var(--space-small);
}
}
> button.select-toggle::before,
> button.select-toggle::after {
content: "";
width: 24px;
height: var(--icon-size-default);
background-repeat: no-repeat;
background-size: var(--icon-size-default) auto;
}
> button.select-toggle::before {
background-image: url("chrome://global/skin/media/audio.svg");
}
> button.select-toggle::after {
background-image: url("chrome://global/skin/icons/arrow-down.svg");
}
&.open > button.select-toggle::after {
background-image: url("chrome://global/skin/icons/arrow-up.svg");
}
> .options {
display: none;
overflow-y: auto;
}
.voiceselect.open > .options {
display: block;
border-top: 1px solid var(--popup-line);
}
> button.option {
background-color: transparent;
text-align: start;
padding-inline-start: var(--space-medium);
}
.voiceselect > .options > button.option {
box-sizing: border-box;
color: var(--popup-button-foreground);
}
.voiceselect > .options > button.option:not(:first-child) {
border-top: 1px solid var(--popup-line);
}
.voiceselect > .options > button.option::-moz-focus-inner {
> button.option::-moz-focus-inner {
outline: none;
border: 0;
}
}
.voiceselect > .options:not(.hovering) > button.option:hover:not(:focus) {
&:not(.hovering) > button.option:hover:not(:focus) {
background-color: transparent;
}
}
}
.voiceselect:not(.open) > button,
.voiceselect .option:last-child {
border-radius: 0 0 3px 3px;
&.open > .options {
display: block;
}
}

View File

@@ -1,16 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<svg xmlns="http://www.w3.org/2000/svg"
width="42"
height="16"
viewBox="0 0 42 16"
fill="context-fill">
<path d="M14.5,7 L8.75,1.25 L10,-1.91791433e-15 L18,8 L17.375,8.625 L10,16 L8.75,14.75 L14.5,9 L1.13686838e-13,9 L1.13686838e-13,7 L14.5,7 Z"/>
<path d="M38.5,7 L32.75,1.25 L34,6.58831647e-15 L42,8 L41.375,8.625 L34,16 L32.75,14.75 L38.5,9 L24,9 L24,7 L38.5,7 Z" transform="translate(33.000000, 8.000000) scale(-1, 1) translate(-33.000000, -8.000000)"/>
</svg>

Before

Width:  |  Height:  |  Size: 744 B

View File

@@ -1,16 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<svg xmlns="http://www.w3.org/2000/svg"
width="44"
height="16"
viewBox="0 0 44 16"
fill="context-fill">
<path d="M14.5,7 L8.75,1.25 L10,-1.91791433e-15 L18,8 L17.375,8.625 L10,16 L8.75,14.75 L14.5,9 L1.13686838e-13,9 L1.13686838e-13,7 L14.5,7 Z" transform="translate(9.000000, 8.000000) scale(-1, 1) translate(-9.000000, -8.000000)"/>
<path d="M40.5,7 L34.75,1.25 L36,-5.17110888e-16 L44,8 L43.375,8.625 L36,16 L34.75,14.75 L40.5,9 L26,9 L26,7 L40.5,7 Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 743 B

View File

@@ -1,18 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<svg xmlns="http://www.w3.org/2000/svg"
width="38"
height="14"
viewBox="0 0 38 14"
fill="context-fill">
<rect x="0" y="0" width="28" height="2"/>
<rect x="0" y="6" width="38" height="2"/>
<rect x="0" y="12" width="18" height="2"/>
</svg>

Before

Width:  |  Height:  |  Size: 520 B

View File

@@ -1,17 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<svg xmlns="http://www.w3.org/2000/svg"
width="38"
height="24"
viewBox="0 0 38 24"
fill="context-fill">
<rect x="0" y="0" width="28" height="2"/>
<rect x="0" y="11" width="38" height="2"/>
<rect x="0" y="22" width="18" height="2"/>
</svg>

Before

Width:  |  Height:  |  Size: 520 B

View File

@@ -1,6 +0,0 @@
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path fill="context-fill" d="M0,13.5v-3h24v3H0z"/>
</svg>

Before

Width:  |  Height:  |  Size: 339 B

View File

@@ -1,6 +0,0 @@
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
<path fill="context-fill" d="M24,13.5H13.5V24h-3V13.5H0v-3h10.5V0h3v10.5H24V13.5z"/>
</svg>

Before

Width:  |  Height:  |  Size: 373 B

View File

@@ -1,13 +0,0 @@
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<svg
xmlns="http://www.w3.org/2000/svg"
width="21"
height="13"
fill="context-fill">
<path d="M 7.276027,7.16854 5.432216,1.80247 3.47265,7.16854 Z M 4.572322,0 H 6.43267 l 4.406957,12.146004 H 9.037157 L 7.805193,8.507991 H 3.001361 L 1.686716,12.146004 H 0 Z"/>
<path
d="m 13.295286,9.789564 q 0,0.64492 0.471288,1.01699 0.471288,0.372069 1.116209,0.372069 0.78548,0 1.521351,-0.363801 1.240232,-0.603579 1.240232,-1.976103 V 7.639828 Q 17.371515,7.813461 16.941568,7.929216 16.511621,8.044971 16.09821,8.09458 L 15.196975,8.210335 Q 14.38669,8.317822 13.981548,8.549332 13.295286,8.937938 13.295286,9.789564 Z m 3.604941,-3.00963 q 0.512629,-0.06614 0.686262,-0.429947 0.09922,-0.198437 0.09922,-0.570507 0,-0.760675 -0.545702,-1.099672 -0.537434,-0.347265 -1.546156,-0.347265 -1.165818,0 -1.653642,0.628384 -0.272851,0.347265 -0.355533,1.033527 h -1.38906 q 0.04134,-1.637106 1.058331,-2.273759 1.025259,-0.64492 2.372977,-0.64492 1.562693,0 2.538342,0.595311 0.967381,0.595311 0.967381,1.85208 v 5.101487 q 0,0.23151 0.09095,0.37207 0.09922,0.140559 0.405142,0.140559 0.09922,0 0.223242,-0.0083 0.124023,-0.01654 0.264583,-0.04134 v 1.099672 q -0.347265,0.09922 -0.529166,0.124024 -0.1819,0.0248 -0.496093,0.0248 -0.768943,0 -1.116208,-0.545702 -0.181901,-0.289387 -0.256315,-0.818553 -0.454752,0.595311 -1.306378,1.033527 -0.851625,0.438215 -1.876884,0.438215 -1.231964,0 -2.017444,-0.744139 -0.777212,-0.752407 -0.777212,-1.876884 0,-1.231964 0.768944,-1.909958 0.768944,-0.677993 2.017444,-0.835089 z M 15.668263,3.075775 Z"
/>
</svg>

Before

Width:  |  Height:  |  Size: 1.7 KiB

View File

@@ -1,11 +0,0 @@
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<svg xmlns="http://www.w3.org/2000/svg" width="21" height="13" fill="context-fill">
<path
d="M 12.088127,11.897958 H 7.2016131 v -0.587043 q 0.6449206,-0.04134 1.0665998,-0.165364 0.4299469,-0.124023 0.4299469,-0.305924 0,-0.07441 -0.01654,-0.181901 -0.01654,-0.107486 -0.04961,-0.190168 L 7.656365,7.838266 H 3.547063 Q 3.315553,8.417041 3.166726,8.846988 3.026166,9.276935 2.910411,9.640736 2.802924,9.996269 2.761583,10.219511 q -0.04134,0.223242 -0.04134,0.363802 0,0.330728 0.520897,0.512629 0.520898,0.1819 1.174087,0.214973 v 0.587043 H 0 v -0.587043 q 0.214974,-0.01654 0.53743401,-0.09095 0.32246003,-0.08268 0.52916499,-0.214974 0.330729,-0.223241 0.51263,-0.46302 0.1819,-0.248046 0.355533,-0.677993 Q 2.819461,7.656365 3.88606,4.90305 4.95266,2.149735 5.787749,0 h 0.661457 l 3.910865,10.120293 q 0.124023,0.32246 0.281119,0.520897 0.157096,0.198437 0.438215,0.388606 0.190169,0.115755 0.496093,0.198437 0.305924,0.07441 0.512629,0.08268 z M 7.3587101,7.102395 5.5810441,2.554878 3.836451,7.102395 Z"
/>
<path
d="m 20.03388,11.749131 q -0.388606,0.140559 -0.686262,0.223241 -0.289387,0.09095 -0.661457,0.09095 -0.64492,0 -1.033526,-0.297656 -0.380338,-0.305924 -0.487825,-0.884699 H 17.1152 q -0.537434,0.595312 -1.15755,0.909504 -0.611848,0.314192 -1.48001,0.314192 -0.917772,0 -1.513083,-0.562239 -0.587043,-0.562238 -0.587043,-1.471742 0,-0.471288 0.132291,-0.843357 0.132291,-0.37207 0.396874,-0.669726 0.206706,-0.248046 0.545702,-0.438215 0.338997,-0.198437 0.636653,-0.314192 0.372069,-0.14056 1.504814,-0.520897 1.141014,-0.380338 1.537888,-0.595312 V 5.87043 q 0,-0.107487 -0.04961,-0.41341 -0.04134,-0.305924 -0.190169,-0.578775 -0.165364,-0.305924 -0.471288,-0.529166 -0.297656,-0.23151 -0.851626,-0.23151 -0.380338,0 -0.711066,0.132291 -0.322461,0.124024 -0.454752,0.264583 0,0.165365 0.07441,0.487825 0.08268,0.32246 0.08268,0.595311 0,0.289388 -0.264583,0.529166 -0.256315,0.239778 -0.719334,0.239778 -0.413411,0 -0.611848,-0.289387 -0.190169,-0.297656 -0.190169,-0.661458 0,-0.380337 0.264583,-0.727602 0.272851,-0.347265 0.702798,-0.620116 0.372069,-0.23151 0.901235,-0.388606 0.529166,-0.165364 1.033527,-0.165364 0.69453,0 1.207159,0.09922 0.520897,0.09095 0.942576,0.405143 0.421679,0.305923 0.636652,0.835089 0.223242,0.520897 0.223242,1.347719 0,1.182354 -0.02481,2.100126 -0.0248,0.909503 -0.0248,1.992639 0,0.32246 0.107487,0.512629 0.115755,0.190169 0.347265,0.322461 0.124023,0.07441 0.388607,0.08268 0.27285,0.0083 0.553969,0.0083 z M 17.148274,7.383514 q -0.702799,0.206705 -1.231964,0.405143 -0.529166,0.198437 -0.983918,0.496092 -0.41341,0.28112 -0.653188,0.669726 -0.239779,0.380337 -0.239779,0.909503 0,0.686262 0.355534,1.008722 0.363801,0.32246 0.917771,0.32246 0.587043,0 1.033527,-0.281119 0.446483,-0.289387 0.752407,-0.677993 z"
/>
</svg>

Before

Width:  |  Height:  |  Size: 3.0 KiB