diff options
Diffstat (limited to 'comm/mail/components/unifiedtoolbar/content/extension-action-button.mjs')
-rw-r--r-- | comm/mail/components/unifiedtoolbar/content/extension-action-button.mjs | 148 |
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", +}); |