summaryrefslogtreecommitdiffstats
path: root/comm/mail/components/unifiedtoolbar/content/extension-action-button.mjs
diff options
context:
space:
mode:
Diffstat (limited to 'comm/mail/components/unifiedtoolbar/content/extension-action-button.mjs')
-rw-r--r--comm/mail/components/unifiedtoolbar/content/extension-action-button.mjs148
1 files changed, 148 insertions, 0 deletions
diff --git a/comm/mail/components/unifiedtoolbar/content/extension-action-button.mjs b/comm/mail/components/unifiedtoolbar/content/extension-action-button.mjs
new file mode 100644
index 0000000000..cc833aae62
--- /dev/null
+++ b/comm/mail/components/unifiedtoolbar/content/extension-action-button.mjs
@@ -0,0 +1,148 @@
+/* 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/. */
+
+import { UnifiedToolbarButton } from "./unified-toolbar-button.mjs";
+
+const lazy = {};
+ChromeUtils.defineESModuleGetters(lazy, {
+ ExtensionParent: "resource://gre/modules/ExtensionParent.sys.mjs",
+});
+let browserActionFor = extensionId => {
+ const extension =
+ lazy.ExtensionParent.GlobalManager.getExtension(extensionId);
+ if (!extension) {
+ return null;
+ }
+ return lazy.ExtensionParent.apiManager.global.browserActionFor(extension);
+};
+
+const BADGE_BACKGROUND_COLOR = "--toolbar-button-badge-bg-color";
+
+/**
+ * Attributes:
+ * - extension: ID of the extension this button is for.
+ * - open: true if the popup is currently open. Gets redirected to aria-pressed.
+ */
+class ExtensionActionButton extends UnifiedToolbarButton {
+ static get observedAttributes() {
+ return super.observedAttributes.concat("open");
+ }
+
+ /**
+ * ext-browserAction instance for this button.
+ *
+ * @type {?ToolbarButtonAPI}
+ */
+ #action = null;
+
+ connectedCallback() {
+ if (this.hasConnected) {
+ super.connectedCallback();
+ if (this.#action?.extension?.hasPermission("menus")) {
+ document.addEventListener("popupshowing", this.#action);
+ }
+ return;
+ }
+ super.connectedCallback();
+ this.#action = browserActionFor(this.getAttribute("extension"));
+ if (!this.#action) {
+ return;
+ }
+ const contextData = this.#action.getContextData(
+ this.#action.getTargetFromWindow(window)
+ );
+ this.applyTabData(contextData);
+ if (this.#action.extension.hasPermission("menus")) {
+ document.addEventListener("popupshowing", this.#action);
+ if (this.#action.defaults.type == "menu") {
+ let menupopup = document.createXULElement("menupopup");
+ menupopup.dataset.actionMenu = this.#action.manifestName;
+ menupopup.dataset.extensionId = this.#action.extension.id;
+ menupopup.addEventListener("popuphiding", event => {
+ if (event.target.state === "open") {
+ return;
+ }
+ this.removeAttribute("aria-pressed");
+ });
+ this.appendChild(menupopup);
+ }
+ }
+ }
+
+ disconnectedCallback() {
+ if (this.#action?.extension?.hasPermission("menus")) {
+ document.removeEventListener("popupshowing", this.#action);
+ }
+ }
+
+ attributeChangedCallback(attribute) {
+ super.attributeChangedCallback(attribute);
+ if (attribute === "open") {
+ if (this.getAttribute("open") === "true") {
+ this.setAttribute("aria-pressed", "true");
+ } else {
+ this.removeAttribute("aria-pressed");
+ }
+ }
+ }
+
+ /**
+ * Apply the data for the current tab to the extension button. Updates title,
+ * label, icon, badge, disabled and popup.
+ *
+ * @param {object} tabData - Properties for the button in the current tab. See
+ * ExtensionToolbarButtons.jsm for more details.
+ */
+ applyTabData(tabData) {
+ if (!this.#action) {
+ this.#action = browserActionFor(this.getAttribute("extension"));
+ }
+ this.title = tabData.title || this.#action.extension.name;
+ this.setAttribute("label", tabData.label || this.title);
+ this.classList.toggle("prefer-icon-only", tabData.label == "");
+ this.badge = tabData.badgeText;
+ this.disabled = !tabData.enabled;
+ const { style } = this.#action.iconData.get(tabData.icon);
+ for (const [propName, value] of style) {
+ this.style.setProperty(propName, value);
+ }
+ if (tabData.badgeText && tabData.badgeBackgroundColor) {
+ const bgColor = tabData.badgeBackgroundColor;
+ this.style.setProperty(
+ BADGE_BACKGROUND_COLOR,
+ `rgba(${bgColor[0]}, ${bgColor[1]}, ${bgColor[2]}, ${bgColor[3] / 255})`
+ );
+ } else {
+ this.style.removeProperty(BADGE_BACKGROUND_COLOR);
+ }
+ this.toggleAttribute("popup", tabData.popup || tabData.type == "menu");
+ if (!tabData.popup) {
+ this.removeAttribute("aria-pressed");
+ }
+ }
+
+ handleClick = event => {
+ // If there is a menupopup associated with this button, open it, instead of
+ // executing the click action.
+ const menupopup = this.querySelector("menupopup");
+ if (menupopup) {
+ event.preventDefault();
+ event.stopPropagation();
+ menupopup.openPopup(this, {
+ position: "after_start",
+ triggerEvent: event,
+ });
+ this.setAttribute("aria-pressed", "true");
+ return;
+ }
+ this.#action?.handleEvent(event);
+ };
+
+ handlePopupShowing(event) {
+ this.#action.handleEvent(event);
+ }
+}
+customElements.define("extension-action-button", ExtensionActionButton, {
+ extends: "button",
+});