Mercurial > addons > firefox-addons > tab-mover
view background.js @ 23:4704e5216412
Create menus on-the-fly
Refactor and eliminate the window tracking code by using the onShown/onHidden
events available in Firefox 60 in order to create menu entries on-the-fly.
Switch from the Firefox-specific contextMenu to the menu API.
author | Guido Berhoerster <guido+tab-mover@berhoerster.name> |
---|---|
date | Sun, 25 Nov 2018 13:27:47 +0100 |
parents | 6b4680867e49 |
children | f418a6305f17 |
line wrap: on
line source
/* * Copyright (C) 2018 Guido Berhoerster <guido+tab-mover@berhoerster.name> * * 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/. */ 'use strict'; const ALLOWED_PROTOCOLS = new Set(['http:', 'https:', 'ftp:']); var windowMenuIds = []; var lastMenuInstanceId = 0; var nextMenuInstanceId = 1; function createMenuItem(createProperties) { return new Promise((resolve, reject) => { let id = browser.menus.create(createProperties, () => { if (browser.runtime.lastError) { reject(browser.runtime.lastError); } else { resolve(id); } }); }); } async function moveTab(tab, targetWindowId) { browser.tabs.move(tab.id, {windowId: targetWindowId, index: -1}); } async function reopenTab(tab, targetWindowId) { if (!ALLOWED_PROTOCOLS.has(new URL(tab.url).protocol)) { // privileged tab URL which cannot be reopened return; } await browser.tabs.create({ url: tab.url, windowId: targetWindowId }); browser.tabs.remove(tab.id); } async function onMenuShown(info, tab) { let menuInstanceId = nextMenuInstanceId++; lastMenuInstanceId = menuInstanceId; let targetWindows = await browser.windows.getAll({ populate: true, windowTypes: ['normal'] }); let creatingMenus = []; let moveMenuItems = 0; let reopenMenuItems = 0; for (let targetWindow of targetWindows) { if (targetWindow.id === tab.windowId) { // ignore active window continue; } if (tab.incognito === targetWindow.incognito) { creatingMenus.push(createMenuItem({ onclick: (info, tab) => moveTab(tab, targetWindow.id), parentId: 'move-menu', title: targetWindow.title })); moveMenuItems++; } else { creatingMenus.push(createMenuItem({ onclick: (info, tab) => reopenTab(tab, targetWindow.id), parentId: 'reopen-menu', title: targetWindow.title })); reopenMenuItems++; } } let updatingMenus = [ browser.menus.update('move-menu', {enabled: moveMenuItems > 0}), browser.menus.update('reopen-menu', {enabled: reopenMenuItems > 0}) ]; await Promise.all([...creatingMenus, ...updatingMenus]); let newWindowMenuIds = await Promise.all(creatingMenus); if (menuInstanceId !== lastMenuInstanceId) { // menu has been closed and opened again, remove the items of this // instance again for (let menuId of newWindowMenuIds) { browser.menus.remove(menuId); } return; } windowMenuIds = newWindowMenuIds; browser.menus.refresh(); } async function onMenuHidden() { lastMenuInstanceId = 0; browser.menus.update('move-menu', {enabled: false}); browser.menus.update('reopen-menu', {enabled: false}); for (let menuId of windowMenuIds) { browser.menus.remove(menuId); } } (async () => { await Promise.all([ // create submenus createMenuItem({ id: 'move-menu', title: browser.i18n.getMessage('moveToWindowMenu'), enabled: false, contexts: ['tab'] }), createMenuItem({ id: 'reopen-menu', title: browser.i18n.getMessage('reopenInWindowMenu'), enabled: false, contexts: ['tab'] }) ]); browser.menus.onShown.addListener(onMenuShown); browser.menus.onHidden.addListener(onMenuHidden); })();