mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-28 15:23:51 +00:00
Bug 1570792 - Toggle extension enabled state on the card r=rpl,fluent-reviewers,Gijs
Differential Revision: https://phabricator.services.mozilla.com/D51699 --HG-- extra : source : cf2f28971e644574fec25c268044bde692511c08
This commit is contained in:
parent
ecb3c6477f
commit
8ff9fdc060
@ -53,7 +53,7 @@ function assertDisabledSideloadedAddonElement(managerWindow, addonElement) {
|
||||
const enableBtn = addonElement.querySelector('[action="toggle-disabled"]');
|
||||
is(
|
||||
doc.l10n.getAttributes(enableBtn).id,
|
||||
"enable-addon-button",
|
||||
"enable-addon-button-label",
|
||||
"The button has the enable label"
|
||||
);
|
||||
}
|
||||
|
@ -12,9 +12,7 @@ async function isExtensionLocked(win, addonID) {
|
||||
await win.htmlBrowserLoaded;
|
||||
return doc.querySelector(`addon-card[addon-id="${addonID}"]`);
|
||||
}, `Get addon-card for "${addonID}"`);
|
||||
let disableBtn = addonCard.querySelector(
|
||||
'panel-item[action="toggle-disabled"]'
|
||||
);
|
||||
let disableBtn = addonCard.querySelector('[action="toggle-disabled"]');
|
||||
let removeBtn = addonCard.querySelector('panel-item[action="remove"]');
|
||||
ok(removeBtn.disabled, "Remove button should be disabled");
|
||||
ok(disableBtn.hidden, "Disable button should be hidden");
|
||||
|
@ -0,0 +1,29 @@
|
||||
# coding=utf8
|
||||
|
||||
# Any copyright is dedicated to the Public Domain.
|
||||
# http://creativecommons.org/publicdomain/zero/1.0/
|
||||
|
||||
from __future__ import absolute_import
|
||||
import fluent.syntax.ast as FTL
|
||||
from fluent.migrate.helpers import transforms_from
|
||||
from fluent.migrate import COPY_PATTERN
|
||||
|
||||
TARGET_FILE = "toolkit/toolkit/about/aboutAddons.ftl"
|
||||
SOURCE_FILE = TARGET_FILE
|
||||
|
||||
|
||||
def migrate(ctx):
|
||||
"""Bug 1570792 - Add a toggle to extension cards, part {index}"""
|
||||
|
||||
ctx.add_transforms(
|
||||
TARGET_FILE,
|
||||
SOURCE_FILE,
|
||||
transforms_from(
|
||||
"""
|
||||
disable-addon-button-label =
|
||||
.aria-label = {COPY_PATTERN(from_path, "disable-addon-button")}
|
||||
enable-addon-button-label =
|
||||
.aria-label = {COPY_PATTERN(from_path, "enable-addon-button")}
|
||||
""",
|
||||
from_path=SOURCE_FILE),
|
||||
)
|
@ -367,6 +367,10 @@ remove-addon-button = Remove
|
||||
remove-addon-disabled-button = Can’t Be Removed <a data-l10n-name="link">Why?</a>
|
||||
disable-addon-button = Disable
|
||||
enable-addon-button = Enable
|
||||
disable-addon-button-label =
|
||||
.aria-label = Disable
|
||||
enable-addon-button-label =
|
||||
.aria-label = Enable
|
||||
preferences-addon-button =
|
||||
{ PLATFORM() ->
|
||||
[windows] Options
|
||||
|
@ -14,6 +14,7 @@
|
||||
|
||||
<link rel="stylesheet" href="chrome://global/skin/in-content/common.css">
|
||||
<link rel="stylesheet" href="chrome://mozapps/content/extensions/aboutaddons.css">
|
||||
<link rel="stylesheet" href="chrome://mozapps/content/extensions/toggle-button.css">
|
||||
<link rel="stylesheet" href="chrome://mozapps/content/extensions/shortcuts.css">
|
||||
|
||||
<link rel="localization" href="branding/brand.ftl">
|
||||
@ -77,7 +78,6 @@
|
||||
|
||||
<template name="addon-options">
|
||||
<panel-list>
|
||||
<panel-item action="toggle-disabled"></panel-item>
|
||||
<panel-item data-l10n-id="remove-addon-button" action="remove"></panel-item>
|
||||
<panel-item data-l10n-id="install-update-button" action="install-update" badged></panel-item>
|
||||
<panel-item data-l10n-id="preferences-addon-button" action="preferences"></panel-item>
|
||||
@ -121,6 +121,7 @@
|
||||
</a>
|
||||
<div class="spacer"></div>
|
||||
<button class="theme-enable-button" action="toggle-disabled" hidden></button>
|
||||
<input type="checkbox" class="toggle-button extension-enable-button" action="toggle-disabled" hidden>
|
||||
<button
|
||||
class="more-options-button"
|
||||
action="more-options"
|
||||
|
@ -1639,18 +1639,6 @@ class AddonOptions extends HTMLElement {
|
||||
case "report":
|
||||
el.hidden = !isAbuseReportSupported(addon);
|
||||
break;
|
||||
case "toggle-disabled":
|
||||
if (addon.type == "theme") {
|
||||
el.remove();
|
||||
} else {
|
||||
let toggleDisabledAction = addon.userDisabled ? "enable" : "disable";
|
||||
document.l10n.setAttributes(
|
||||
el,
|
||||
`${toggleDisabledAction}-addon-button`
|
||||
);
|
||||
el.hidden = !hasPermission(addon, toggleDisabledAction);
|
||||
}
|
||||
break;
|
||||
case "install-update":
|
||||
el.hidden = !updateInstall;
|
||||
break;
|
||||
@ -2452,8 +2440,8 @@ class AddonCard extends HTMLElement {
|
||||
await addon.disable();
|
||||
}
|
||||
if (e.mozInputSource == MouseEvent.MOZ_SOURCE_KEYBOARD) {
|
||||
// Refocus the open menu button so it's clear where the focus is.
|
||||
this.querySelector('[action="more-options"]').focus();
|
||||
// Refocus the button, since the card might've moved and lost focus.
|
||||
e.target.focus();
|
||||
}
|
||||
break;
|
||||
case "ask-to-activate":
|
||||
@ -2747,6 +2735,12 @@ class AddonCard extends HTMLElement {
|
||||
toggleDisabledButton,
|
||||
`${toggleDisabledAction}-addon-button`
|
||||
);
|
||||
} else if (addon.type === "extension") {
|
||||
toggleDisabledButton.checked = !addon.userDisabled;
|
||||
document.l10n.setAttributes(
|
||||
toggleDisabledButton,
|
||||
`${toggleDisabledAction}-addon-button-label`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2847,6 +2841,9 @@ class AddonCard extends HTMLElement {
|
||||
if (addon.type != "theme") {
|
||||
this.card.querySelector(".theme-enable-button").remove();
|
||||
}
|
||||
if (addon.type != "extension") {
|
||||
this.card.querySelector(".extension-enable-button").remove();
|
||||
}
|
||||
|
||||
let nameContainer = this.card.querySelector(".addon-name-container");
|
||||
let headingLevel = this.expanded ? "h1" : "h3";
|
||||
|
72
toolkit/mozapps/extensions/content/toggle-button.css
Normal file
72
toolkit/mozapps/extensions/content/toggle-button.css
Normal file
@ -0,0 +1,72 @@
|
||||
/* 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/. */
|
||||
|
||||
input[type="checkbox"].toggle-button {
|
||||
--button-height: 16px;
|
||||
--button-half-height: 8px;
|
||||
--button-width: 26px;
|
||||
--button-border-width: 1px;
|
||||
/* dot-size = button-height - 2*dot-margin - 2*button-border-width */
|
||||
--dot-size: 10px;
|
||||
--dot-margin: 2px;
|
||||
/* --dot-transform-x = button-width - 2*dot-margin - dot-size - 2*button-border-width */
|
||||
--dot-transform-x: 10px;
|
||||
--border-color: hsla(210,4%,10%,.14);
|
||||
}
|
||||
|
||||
input[type="checkbox"].toggle-button {
|
||||
-moz-appearance: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
outline: 0;
|
||||
border: var(--button-border-width) solid var(--border-color);
|
||||
height: var(--button-height);
|
||||
width: var(--button-width);
|
||||
border-radius: var(--button-half-height);
|
||||
background: var(--in-content-button-background);
|
||||
box-sizing: border-box;
|
||||
}
|
||||
input[type="checkbox"].toggle-button:hover {
|
||||
background: var(--in-content-button-background-hover);
|
||||
border-color: var(--border-color);
|
||||
}
|
||||
input[type="checkbox"].toggle-button:active {
|
||||
background: var(--in-content-button-background-active);
|
||||
border-color: var(--border-color);
|
||||
}
|
||||
input[type="checkbox"].toggle-button:focus {
|
||||
box-shadow: 0 0 0 1px var(--border-color), 0 0 0 4px rgba(10, 132, 255, 0.3);
|
||||
}
|
||||
input[type="checkbox"].toggle-button:checked:focus {
|
||||
box-shadow: 0 0 0 1px var(--in-content-border-active), 0 0 0 4px rgba(10, 132, 255, 0.3);
|
||||
}
|
||||
|
||||
input[type="checkbox"].toggle-button:checked {
|
||||
background: var(--in-content-primary-button-background);
|
||||
border-color: var(--in-content-primary-button-background-hover);
|
||||
}
|
||||
input[type="checkbox"].toggle-button:checked:hover {
|
||||
background: var(--in-content-primary-button-background-hover);
|
||||
border-color: var(--in-content-primary-button-background-active);
|
||||
}
|
||||
input[type="checkbox"].toggle-button:checked:active {
|
||||
background: var(--in-content-primary-button-background-active);
|
||||
border-color: var(--in-content-primary-button-background-active);
|
||||
}
|
||||
|
||||
input[type="checkbox"].toggle-button::before {
|
||||
display: block;
|
||||
content: "";
|
||||
background: #fff;
|
||||
height: var(--dot-size);
|
||||
width: var(--dot-size);
|
||||
margin: var(--dot-margin);
|
||||
border-radius: 50%;
|
||||
outline: 1px solid var(--border-color);
|
||||
-moz-outline-radius: 50%;
|
||||
transition: transform 100ms;
|
||||
}
|
||||
input[type="checkbox"].toggle-button:checked::before {
|
||||
transform: translateX(var(--dot-transform-x));
|
||||
}
|
@ -33,4 +33,5 @@ toolkit.jar:
|
||||
content/mozapps/extensions/rating-star.css (content/rating-star.css)
|
||||
content/mozapps/extensions/shortcuts.css (content/shortcuts.css)
|
||||
content/mozapps/extensions/shortcuts.js (content/shortcuts.js)
|
||||
content/mozapps/extensions/toggle-button.css (content/toggle-button.css)
|
||||
#endif
|
||||
|
@ -19,7 +19,7 @@ function assertDisabledSideloadedExtensionElement(managerWindow, addonElement) {
|
||||
);
|
||||
is(
|
||||
doc.l10n.getAttributes(toggleDisabled).id,
|
||||
"enable-addon-button",
|
||||
"enable-addon-button-label",
|
||||
"Addon toggle-disabled action has the enable label"
|
||||
);
|
||||
}
|
||||
@ -31,7 +31,7 @@ function assertEnabledSideloadedExtensionElement(managerWindow, addonElement) {
|
||||
);
|
||||
is(
|
||||
doc.l10n.getAttributes(toggleDisabled).id,
|
||||
"enable-addon-button",
|
||||
"enable-addon-button-label",
|
||||
"Addon toggle-disabled action has the enable label"
|
||||
);
|
||||
}
|
||||
|
@ -293,7 +293,7 @@ add_task(async function testDetailOperations() {
|
||||
let panel = card.querySelector("panel-list");
|
||||
|
||||
// Check button visibility.
|
||||
let disableButton = panel.querySelector('[action="toggle-disabled"]');
|
||||
let disableButton = card.querySelector('[action="toggle-disabled"]');
|
||||
ok(!disableButton.hidden, "The disable button is visible");
|
||||
|
||||
let removeButton = panel.querySelector('[action="remove"]');
|
||||
|
@ -106,15 +106,18 @@ add_task(async function testExtensionList() {
|
||||
ok(icon.src.endsWith("/test-icon.png"), "The icon is set");
|
||||
|
||||
// Disable the extension.
|
||||
let disableButton = card.querySelector('[action="toggle-disabled"]');
|
||||
let disableToggle = card.querySelector('[action="toggle-disabled"]');
|
||||
ok(disableToggle.checked, "The disable toggle is checked");
|
||||
is(
|
||||
doc.l10n.getAttributes(disableButton).id,
|
||||
"disable-addon-button",
|
||||
"The button has the disable label"
|
||||
doc.l10n.getAttributes(disableToggle).id,
|
||||
"disable-addon-button-label",
|
||||
"The toggle has the disable label"
|
||||
);
|
||||
ok(disableToggle.getAttribute("aria-label"), "There's an aria-label");
|
||||
ok(!disableToggle.hidden, "The toggle is visible");
|
||||
|
||||
let disabled = BrowserTestUtils.waitForEvent(list, "move");
|
||||
disableButton.click();
|
||||
disableToggle.click();
|
||||
await disabled;
|
||||
is(
|
||||
card.parentNode,
|
||||
@ -123,11 +126,13 @@ add_task(async function testExtensionList() {
|
||||
);
|
||||
|
||||
// The disable button is now enable.
|
||||
ok(!disableToggle.checked, "The disable toggle is unchecked");
|
||||
is(
|
||||
doc.l10n.getAttributes(disableButton).id,
|
||||
"enable-addon-button",
|
||||
doc.l10n.getAttributes(disableToggle).id,
|
||||
"enable-addon-button-label",
|
||||
"The button has the enable label"
|
||||
);
|
||||
ok(disableToggle.getAttribute("aria-label"), "There's an aria-label");
|
||||
|
||||
// Remove the add-on.
|
||||
let removeButton = card.querySelector('[action="remove"]');
|
||||
@ -395,63 +400,47 @@ add_task(async function testKeyboardSupport() {
|
||||
// Test opening and closing the menu.
|
||||
let moreOptionsMenu = card.querySelector("panel-list");
|
||||
let expandButton = moreOptionsMenu.querySelector('[action="expand"]');
|
||||
let toggleDisableButton = card.querySelector('[action="toggle-disabled"]');
|
||||
let removeButton = card.querySelector('[action="remove"]');
|
||||
is(moreOptionsMenu.open, false, "The menu is closed");
|
||||
let shown = BrowserTestUtils.waitForEvent(moreOptionsMenu, "shown");
|
||||
space();
|
||||
await shown;
|
||||
is(moreOptionsMenu.open, true, "The menu is open");
|
||||
isFocused(toggleDisableButton, "The disable button is now focused");
|
||||
EventUtils.synthesizeKey("Escape", {});
|
||||
is(moreOptionsMenu.open, false, "The menu is closed");
|
||||
isFocused(moreOptionsButton, "The more options button is focused");
|
||||
|
||||
// Test tabbing out of the menu.
|
||||
space();
|
||||
shown = BrowserTestUtils.waitForEvent(moreOptionsMenu, "shown");
|
||||
is(moreOptionsMenu.open, true, "The menu is open");
|
||||
await shown;
|
||||
isFocused(removeButton, "The remove button is now focused");
|
||||
tab({ shiftKey: true });
|
||||
is(moreOptionsMenu.open, true, "The menu stays open");
|
||||
isFocused(expandButton, "The focus has looped to the bottom");
|
||||
tab();
|
||||
is(moreOptionsMenu.open, true, "The menu stays open");
|
||||
isFocused(toggleDisableButton, "The focus has looped to the top");
|
||||
isFocused(removeButton, "The focus has looped to the top");
|
||||
|
||||
let hidden = BrowserTestUtils.waitForEvent(moreOptionsMenu, "hidden");
|
||||
EventUtils.synthesizeKey("Escape", {});
|
||||
await hidden;
|
||||
isFocused(moreOptionsButton, "Escape closed the menu");
|
||||
|
||||
// Open the menu to test contents.
|
||||
shown = BrowserTestUtils.waitForEvent(moreOptionsMenu, "shown");
|
||||
space();
|
||||
is(moreOptionsMenu.open, true, "The menu is open");
|
||||
// Wait for the panel to be shown.
|
||||
await shown;
|
||||
|
||||
// Disable the add-on.
|
||||
isFocused(toggleDisableButton, "The disable button is focused");
|
||||
let disableButton = card.querySelector('[action="toggle-disabled"]');
|
||||
tab({ shiftKey: true });
|
||||
isFocused(disableButton, "The disable toggle is focused");
|
||||
is(card.parentNode, enabledSection, "The card is in the enabled section");
|
||||
let disabled = BrowserTestUtils.waitForEvent(list, "move");
|
||||
space();
|
||||
await disabled;
|
||||
is(moreOptionsMenu.open, false, "The menu is closed");
|
||||
is(
|
||||
card.parentNode,
|
||||
disabledSection,
|
||||
"The card is now in the disabled section"
|
||||
);
|
||||
|
||||
// Open the menu again.
|
||||
shown = BrowserTestUtils.waitForEvent(moreOptionsMenu, "shown");
|
||||
isFocused(moreOptionsButton, "The more options button is focused");
|
||||
space();
|
||||
await shown;
|
||||
isFocused(disableButton, "The disable button is still focused");
|
||||
|
||||
// Remove the add-on.
|
||||
tab();
|
||||
let removeButton = card.querySelector('[action="remove"]');
|
||||
isFocused(moreOptionsButton, "The more options button is focused again");
|
||||
shown = BrowserTestUtils.waitForEvent(moreOptionsMenu, "shown");
|
||||
space();
|
||||
is(moreOptionsMenu.open, true, "The menu is open");
|
||||
await shown;
|
||||
isFocused(removeButton, "The remove button is focused");
|
||||
let removed = BrowserTestUtils.waitForEvent(list, "remove");
|
||||
space();
|
||||
@ -763,8 +752,9 @@ add_task(async function testSideloadRemoveButton() {
|
||||
let card = getCardByAddonId(doc, id);
|
||||
|
||||
let moreOptionsPanel = card.querySelector("panel-list");
|
||||
let moreOptionsButton = card.querySelector('[action="more-options"]');
|
||||
let panelOpened = BrowserTestUtils.waitForEvent(moreOptionsPanel, "shown");
|
||||
moreOptionsPanel.show();
|
||||
EventUtils.synthesizeMouseAtCenter(moreOptionsButton, {}, win);
|
||||
await panelOpened;
|
||||
|
||||
// Verify the remove button is visible with a SUMO link.
|
||||
|
@ -16,7 +16,8 @@ async function getUpdateButton(item) {
|
||||
let button = item.querySelector('[action="install-update"]');
|
||||
let panel = button.closest("panel-list");
|
||||
let shown = BrowserTestUtils.waitForEvent(panel, "shown");
|
||||
panel.show();
|
||||
let moreOptionsButton = item.querySelector('[action="more-options"]');
|
||||
EventUtils.synthesizeMouseAtCenter(moreOptionsButton, {}, item.ownerGlobal);
|
||||
await shown;
|
||||
return button;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user