|
- /* Helper to manage the visibility and icon of a pageAction button.
- * Each callback is evaluated whenever the tab has changed.
- * Callbacks may be async (i.e. return a Promise).
- *
- * Arguments:
- * - options.visible: Tab => boolean; whether to show the pageAction button
- * - options.icon: Tab => either a string (the icon path), or null (to get the
- * default icon from the manifest), or an object (with path or imageData, see
- * docs of browser.pageAction.setIcon).
- * - options.title: Tab => string (to use as button tooltip), or null (to use
- * default title from the manifest)
- * - options.onClicked: Tab => void; executed on click, after which the button
- * state is automatically updated on all tabs.
- *
- * Returns an object with the following methods:
- * - update(tab?): update visibility, icons, etcetera of a given tab, or of
- * all tabs if the tab argument is omitted.
- *
- * Example usage:
- * const pageActionButton = PageActionButton({
- * visible: tab => tab.url.startsWith('https'),
- * icon: tab => isEnabled(tab.url) ? '/icon_enabled.svg' : '/icon_disabled.svg',
- * title: tab => isEnabled(tab.url) ? 'Disable' : 'Enable',
- * onClicked: tab => toggleEnabled(tab.url),
- * })
- * // Manually trigger an update of a tab.
- * pageActionButton.update(tab)
- */
-
- import browser from 'webextension-polyfill'
-
-
- export default function PageActionButton({
- visible = tab => true,
- icon = tab => null,
- title = tab => null,
- onClicked = tab => {},
- }) {
- async function setIcon(tab) {
- let iconSetting = await icon(tab)
- if (typeof iconSetting === 'string' || iconSetting === null) {
- iconSetting = { path: iconSetting }
- }
- browser.pageAction.setIcon({
- ...iconSetting,
- tabId: tab.id,
- })
- }
-
- async function setTitle(tab) {
- browser.pageAction.setTitle({
- title: await title(tab),
- tabId: tab.id,
- })
- }
-
- async function checkTab(tab) {
- if (await visible(tab)) {
- setIcon(tab)
- setTitle(tab)
- browser.pageAction.show(tab.id)
- } else {
- browser.pageAction.hide(tab.id)
- }
- }
-
- async function checkAllTabs() {
- const tabs = await browser.tabs.query({})
- for (const tab of tabs) {
- await checkTab(tab)
- }
- }
-
- // Show/hide the button on current tabs (XXX not awaiting it's completion)
- checkAllTabs()
-
- // Show/hide the button whenever a tab changes.
- browser.tabs.onUpdated.addListener((id, changeInfo, tab) => {
- checkTab(tab)
- });
-
- // Handle button clicks
- browser.pageAction.onClicked.addListener(async tab => {
- await onClicked(tab)
- await checkAllTabs(tab)
- })
-
- return {
- update: tab => tab ? checkTab(tab) : checkAllTabs()
- }
- }
|