diff --git a/duplicate-tabs-closer-master/README.md b/duplicate-tabs-closer-master/README.md index 73d429a..0652d12 100644 --- a/duplicate-tabs-closer-master/README.md +++ b/duplicate-tabs-closer-master/README.md @@ -3,9 +3,10 @@ deDup2Activate detects and closes duplicate tabs. -* Use the WebExtensions API -* Support [Firefox](https://addons.mozilla.org/en-US/firefox/addon/duplicate-tabs-closer) and [Chrome](https://chrome.google.com/webstore/detail/duplicate-tabs-closer/gnmdbogfankgjepgglmmfmbnimcmcjle) -* Firefox Container Tab feature is supported. +* Use the WebExtensions API +* Support [Firefox](https://addons.mozilla.org/en-US/firefox/addon/duplicate-tabs-closer) and [Chrome](https://chrome.google.com/webstore/detail/duplicate-tabs-closer/gnmdbogfankgjepgglmmfmbnimcmcjle) +* Firefox Container Tab feature is supported. +* Includes a toolbar context menu item **Duplicate Tab Closer** to trigger a manual duplicate sweep. ## Options: diff --git a/duplicate-tabs-closer-master/_locales/en/messages.json b/duplicate-tabs-closer-master/_locales/en/messages.json index 0a23e5d..ccc1066 100644 --- a/duplicate-tabs-closer-master/_locales/en/messages.json +++ b/duplicate-tabs-closer-master/_locales/en/messages.json @@ -11,10 +11,14 @@ "message": "Do nothing", "description": "Do nothing" }, - "autoCloseTab": { - "message": "Close tab automatically", - "description": "Close tab automatically" - }, + "autoCloseTab": { + "message": "Close tab automatically", + "description": "Close tab automatically" + }, + "contextMenuCloseDuplicates": { + "message": "Duplicate Tab Closer", + "description": "Context menu item that closes duplicate tabs" + }, "showPanel": { "message": "Show panel", "description": "Show panel" diff --git a/duplicate-tabs-closer-master/_locales/fr/messages.json b/duplicate-tabs-closer-master/_locales/fr/messages.json index 100ed48..5f9cb5f 100644 --- a/duplicate-tabs-closer-master/_locales/fr/messages.json +++ b/duplicate-tabs-closer-master/_locales/fr/messages.json @@ -11,10 +11,14 @@ "message": "Ne rien faire", "description": "Do nothing" }, - "autoCloseTab": { - "message": "Fermer l'onglet automatiquement", - "description": "Close tab automatically" - }, + "autoCloseTab": { + "message": "Fermer l'onglet automatiquement", + "description": "Close tab automatically" + }, + "contextMenuCloseDuplicates": { + "message": "Fermer les onglets dupliqués", + "description": "Context menu item that closes duplicate tabs" + }, "showPanel": { "message": "Afficher le panneau", "description": "Show panel" diff --git a/duplicate-tabs-closer-master/_locales/ja/messages.json b/duplicate-tabs-closer-master/_locales/ja/messages.json index aa4d5d5..8109bbe 100644 --- a/duplicate-tabs-closer-master/_locales/ja/messages.json +++ b/duplicate-tabs-closer-master/_locales/ja/messages.json @@ -11,10 +11,14 @@ "message": "何もしない", "description": "Do nothing" }, - "autoCloseTab": { - "message": "自動的にタブを閉じる", - "description": "Close tab automatically" - }, + "autoCloseTab": { + "message": "自動的にタブを閉じる", + "description": "Close tab automatically" + }, + "contextMenuCloseDuplicates": { + "message": "重複タブを閉じる", + "description": "Context menu item that closes duplicate tabs" + }, "showPanel": { "message": "パネルを表示する", "description": "Show panel" diff --git a/duplicate-tabs-closer-master/_locales/ru/messages.json b/duplicate-tabs-closer-master/_locales/ru/messages.json index bc3c231..eacfec2 100644 --- a/duplicate-tabs-closer-master/_locales/ru/messages.json +++ b/duplicate-tabs-closer-master/_locales/ru/messages.json @@ -11,10 +11,14 @@ "message": "Ничего не делать", "description": "Do nothing" }, - "autoCloseTab": { - "message": "Закрыть вкладку автоматически", - "description": "Close tab automatically" - }, + "autoCloseTab": { + "message": "Закрыть вкладку автоматически", + "description": "Close tab automatically" + }, + "contextMenuCloseDuplicates": { + "message": "Закрыть дубликаты вкладок", + "description": "Context menu item that closes duplicate tabs" + }, "showPanel": { "message": "Показать панель", "description": "Show panel" diff --git a/duplicate-tabs-closer-master/_locales/uk/messages.json b/duplicate-tabs-closer-master/_locales/uk/messages.json index 6c79e8e..d4eff0c 100644 --- a/duplicate-tabs-closer-master/_locales/uk/messages.json +++ b/duplicate-tabs-closer-master/_locales/uk/messages.json @@ -11,10 +11,14 @@ "message": "Нічого не робити", "description": "Do nothing" }, - "autoCloseTab": { - "message": "Закрити вкладку автоматично", - "description": "Close tab automatically" - }, + "autoCloseTab": { + "message": "Закрити вкладку автоматично", + "description": "Close tab automatically" + }, + "contextMenuCloseDuplicates": { + "message": "Закрити дублікати вкладок", + "description": "Context menu item that closes duplicate tabs" + }, "showPanel": { "message": "Показати панель", "description": "Show panel" diff --git a/duplicate-tabs-closer-master/_locales/zh_CN/messages.json b/duplicate-tabs-closer-master/_locales/zh_CN/messages.json index 055a3a4..35ea996 100644 --- a/duplicate-tabs-closer-master/_locales/zh_CN/messages.json +++ b/duplicate-tabs-closer-master/_locales/zh_CN/messages.json @@ -14,11 +14,16 @@ "description": "Do nothing", "hash": "a0a28b9a09a44d3e69599b6500e47a0e" }, - "autoCloseTab": { - "message": "自动关闭标签页", - "description": "Close tab automatically", - "hash": "6096376eef1def5290ffc9e691152903" - }, + "autoCloseTab": { + "message": "自动关闭标签页", + "description": "Close tab automatically", + "hash": "6096376eef1def5290ffc9e691152903" + }, + "contextMenuCloseDuplicates": { + "message": "关闭重复标签页", + "description": "Context menu item that closes duplicate tabs", + "hash": "1f2e3d4c5b6a79808796a5b4c3d2e1f0" + }, "showPanel": { "message": "显示面板", "description": "Show panel", diff --git a/duplicate-tabs-closer-master/background.js b/duplicate-tabs-closer-master/background.js index 32464ec..676b811 100644 --- a/duplicate-tabs-closer-master/background.js +++ b/duplicate-tabs-closer-master/background.js @@ -84,8 +84,11 @@ class TabsInfo { } -// eslint-disable-next-line no-unused-vars -const tabsInfo = new TabsInfo();"use strict"; +// eslint-disable-next-line no-unused-vars +const tabsInfo = new TabsInfo(); + +const CONTEXT_MENU_CLOSE_DUPLICATES_ID = "close-duplicate-tabs"; +"use strict"; const defaultOptions = { shrunkMode: { @@ -646,8 +649,44 @@ const searchForDuplicateTabs = async (windowId, closeTabs) => { } }; -// eslint-disable-next-line no-unused-vars -const closeDuplicateTabs = (windowId) => searchForDuplicateTabs(windowId, true); +// eslint-disable-next-line no-unused-vars +const closeDuplicateTabs = (windowId) => searchForDuplicateTabs(windowId, true); + +const getContextMenusApi = () => { + if (chrome.contextMenus) return chrome.contextMenus; + if (typeof browser !== "undefined" && browser.contextMenus) return browser.contextMenus; + return null; +}; + +const createContextMenus = () => { + const contextMenus = getContextMenusApi(); + if (!contextMenus) return; + contextMenus.removeAll(() => { + const title = chrome.i18n.getMessage("contextMenuCloseDuplicates") || "Duplicate Tab Closer"; + const contexts = ["action"]; + try { + contextMenus.create({ + id: CONTEXT_MENU_CLOSE_DUPLICATES_ID, + title: title, + contexts: contexts + }); + } catch (error) { + console.error("createContextMenus error:", error); + } + }); +}; + +const handleContextMenuClick = async (info, tab) => { + if (info.menuItemId !== CONTEXT_MENU_CLOSE_DUPLICATES_ID) return; + let windowId = typeof info.windowId !== "undefined" ? info.windowId : undefined; + if (typeof windowId === "undefined" && tab && typeof tab.windowId !== "undefined") { + windowId = tab.windowId; + } + if (typeof windowId === "undefined") { + windowId = await getActiveWindowId(); + } + closeDuplicateTabs(windowId); +}; const setDuplicateTabPanel = async (duplicateTab, duplicateTabs) => { let containerColor = ""; @@ -730,7 +769,11 @@ const handleMessage = (message, sender, response) => { } }; -chrome.runtime.onMessage.addListener(handleMessage);"use strict"; +chrome.runtime.onMessage.addListener(handleMessage); + +const contextMenusApi = getContextMenusApi(); +if (contextMenusApi) contextMenusApi.onClicked.addListener(handleContextMenuClick); +"use strict"; const onCreatedTab = (tab) => { tabsInfo.setNewTab(tab.id); @@ -809,6 +852,7 @@ const start = async () => { await initializeOptions(); setBadgeIcon(); await refreshGlobalDuplicateTabsInfo(); + createContextMenus(); chrome.tabs.onCreated.addListener(onCreatedTab); chrome.webNavigation.onBeforeNavigate.addListener(onBeforeNavigate); chrome.tabs.onAttached.addListener(onAttached); diff --git a/duplicate-tabs-closer-master/manifest-c.json b/duplicate-tabs-closer-master/manifest-c.json index ed4c5e0..153105f 100644 --- a/duplicate-tabs-closer-master/manifest-c.json +++ b/duplicate-tabs-closer-master/manifest-c.json @@ -22,6 +22,7 @@ "permissions": [ "tabs", "webNavigation", + "contextMenus", "storage" ], "options_ui": { diff --git a/duplicate-tabs-closer-master/manifest-f.json b/duplicate-tabs-closer-master/manifest-f.json index a6ac457..216b16f 100644 --- a/duplicate-tabs-closer-master/manifest-f.json +++ b/duplicate-tabs-closer-master/manifest-f.json @@ -33,6 +33,7 @@ "cookies", "tabs", "webNavigation", + "contextMenus", "storage", "contextualIdentities" ],