From 6a2c50a89f85a8a9fb6e511292dac29544b118f9 Mon Sep 17 00:00:00 2001 From: Anton Dudakov Date: Fri, 21 Feb 2025 16:19:06 +0400 Subject: [PATCH 1/3] adds an ability to reopen current tab in the specific container with a shortcut --- package-lock.json | 28 +++++------- src/js/background/backgroundLogic.js | 37 +++++++++++++--- src/manifest.json | 60 ++++++++++++++++++++++++++ test/features/reopen-shortcuts.test.js | 44 +++++++++++++++++++ 4 files changed, 146 insertions(+), 23 deletions(-) create mode 100644 test/features/reopen-shortcuts.test.js diff --git a/package-lock.json b/package-lock.json index c9da2dc..0ce68d9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "testpilot-containers", - "version": "8.1.3", + "version": "8.2.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "testpilot-containers", - "version": "8.1.1", + "version": "8.2.0", "license": "MPL-2.0", "devDependencies": { "addons-linter": "^5.28.0", @@ -15032,8 +15032,7 @@ "version": "5.3.2", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "requires": {} + "dev": true }, "acorn-walk": { "version": "7.2.0", @@ -17246,15 +17245,13 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/eslint-plugin-no-unsanitized/-/eslint-plugin-no-unsanitized-4.0.2.tgz", "integrity": "sha512-Pry0S9YmHoz8NCEMRQh7N0Yexh2MYCNPIlrV52hTmS7qXnTghWsjXouF08bgsrrZqaW9tt1ZiK3j5NEmPE+EjQ==", - "dev": true, - "requires": {} + "dev": true }, "eslint-plugin-promise": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-5.2.0.tgz", "integrity": "sha512-SftLb1pUG01QYq2A/hGAWfDRXqYD82zE7j7TopDOyNdU+7SvvoXREls/+PRTY17vUXzXnZA/zfnyKgRH6x4JJw==", - "dev": true, - "requires": {} + "dev": true }, "eslint-scope": { "version": "5.1.1", @@ -19763,8 +19760,7 @@ "version": "7.5.9", "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", - "dev": true, - "requires": {} + "dev": true } } }, @@ -21971,8 +21967,7 @@ "version": "0.36.2", "resolved": "https://registry.npmjs.org/postcss-syntax/-/postcss-syntax-0.36.2.tgz", "integrity": "sha512-nBRg/i7E3SOHWxF3PpF5WnJM/jQ1YpY9000OaVXlAQj6Zp/kIqJxEDWIZ67tAd7NLuk7zqN4yqe9nc0oNAOs1w==", - "dev": true, - "requires": {} + "dev": true }, "postcss-value-parser": { "version": "4.2.0", @@ -22826,8 +22821,7 @@ "version": "3.7.0", "resolved": "https://registry.npmjs.org/sinon-chai/-/sinon-chai-3.7.0.tgz", "integrity": "sha512-mf5NURdUaSdnatJx3uhoBOrY9dtL19fiOtAdT1Azxg3+lNJFiuN0uzaU3xX1LeAfL17kHQhTAJgpsfhbMJMY2g==", - "dev": true, - "requires": {} + "dev": true }, "slash": { "version": "3.0.0", @@ -23571,8 +23565,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-3.0.0.tgz", "integrity": "sha512-F6yTRuc06xr1h5Qw/ykb2LuFynJ2IxkKfCMf+1xqPffkxh0S09Zc902XCffcsw/XMFq/OzQ1w54fLIDtmRNHnQ==", - "dev": true, - "requires": {} + "dev": true }, "stylelint-config-standard": { "version": "20.0.0", @@ -24946,8 +24939,7 @@ "version": "8.12.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.12.0.tgz", "integrity": "sha512-kU62emKIdKVeEIOIKVegvqpXMSTAMLJozpHZaJNDYqBjzlSYXQGviYwN1osDLJ9av68qHd4a2oSjd7yD4pacig==", - "dev": true, - "requires": {} + "dev": true }, "xdg-basedir": { "version": "5.1.0", diff --git a/src/js/background/backgroundLogic.js b/src/js/background/backgroundLogic.js index d21cf33..3e7cddc 100644 --- a/src/js/background/backgroundLogic.js +++ b/src/js/background/backgroundLogic.js @@ -13,9 +13,9 @@ const backgroundLogic = { ]), NUMBER_OF_KEYBOARD_SHORTCUTS: 10, unhideQueue: [], - init() { - browser.commands.onCommand.addListener(function (command) { + async init() { + browser.commands.onCommand.addListener(async function (command) { if (command === "sort_tabs") { backgroundLogic.sortTabs(); return; @@ -23,10 +23,33 @@ const backgroundLogic = { for (let i=0; i < backgroundLogic.NUMBER_OF_KEYBOARD_SHORTCUTS; i++) { const key = "open_container_" + i; + const reopenKey = "reopen_in_container_" + i; const cookieStoreId = identityState.keyboardShortcut[key]; + + if (cookieStoreId === "none") { + continue; + } + if (command === key) { - if (cookieStoreId === "none") return; browser.tabs.create({cookieStoreId}); + return; + } + + if (command === reopenKey) { + const currentTab = await browser.tabs.query({active: true, currentWindow: true}); + if (currentTab.length > 0) { + const tab = currentTab[0]; + + await browser.tabs.create({ + url: tab.url, + cookieStoreId: cookieStoreId, + index: tab.index + 1, + active: tab.active + }); + + await browser.tabs.remove(tab.id); + } + return; } } }); @@ -70,10 +93,14 @@ const backgroundLogic = { updateTranslationInManifest() { for (let index = 0; index < 10; index++) { - const ajustedIndex = index + 1; // We want to start from 1 instead of 0 in the UI. + const adjustedIndex = index + 1; browser.commands.update({ name: `open_container_${index}`, - description: browser.i18n.getMessage("containerShortcut", `${ajustedIndex}`) + description: browser.i18n.getMessage("containerShortcut", `${adjustedIndex}`) + }); + browser.commands.update({ + name: `reopen_in_container_${index}`, + description: browser.i18n.getMessage("reopenInContainerShortcut", `${adjustedIndex}`) }); } }, diff --git a/src/manifest.json b/src/manifest.json index c87c44c..068bb6c 100644 --- a/src/manifest.json +++ b/src/manifest.json @@ -106,6 +106,66 @@ "default": "Ctrl+Shift+0" }, "description": "__MSG_containerShortcut__" + }, + "reopen_in_container_0": { + "suggested_key": { + "default": "Alt+Shift+1" + }, + "description": "__MSG_reopenInContainerShortcut__" + }, + "reopen_in_container_1": { + "suggested_key": { + "default": "Alt+Shift+2" + }, + "description": "__MSG_reopenInContainerShortcut__" + }, + "reopen_in_container_2": { + "suggested_key": { + "default": "Alt+Shift+3" + }, + "description": "__MSG_reopenInContainerShortcut__" + }, + "reopen_in_container_3": { + "suggested_key": { + "default": "Alt+Shift+4" + }, + "description": "__MSG_reopenInContainerShortcut__" + }, + "reopen_in_container_4": { + "suggested_key": { + "default": "Alt+Shift+5" + }, + "description": "__MSG_reopenInContainerShortcut__" + }, + "reopen_in_container_5": { + "suggested_key": { + "default": "Alt+Shift+6" + }, + "description": "__MSG_reopenInContainerShortcut__" + }, + "reopen_in_container_6": { + "suggested_key": { + "default": "Alt+Shift+7" + }, + "description": "__MSG_reopenInContainerShortcut__" + }, + "reopen_in_container_7": { + "suggested_key": { + "default": "Alt+Shift+8" + }, + "description": "__MSG_reopenInContainerShortcut__" + }, + "reopen_in_container_8": { + "suggested_key": { + "default": "Alt+Shift+9" + }, + "description": "__MSG_reopenInContainerShortcut__" + }, + "reopen_in_container_9": { + "suggested_key": { + "default": "Alt+Shift+0" + }, + "description": "__MSG_reopenInContainerShortcut__" } }, "browser_action": { diff --git a/test/features/reopen-shortcuts.test.js b/test/features/reopen-shortcuts.test.js new file mode 100644 index 0000000..ac3781c --- /dev/null +++ b/test/features/reopen-shortcuts.test.js @@ -0,0 +1,44 @@ +const {initializeWithTab} = require("../common"); + +describe("Reopen Shortcuts Feature", function () { + beforeEach(async function () { + // Initialize with a tab in the default container + this.webExt = await initializeWithTab({ + cookieStoreId: "firefox-default", + url: "https://example.com" + }); + }); + + afterEach(function () { + this.webExt.destroy(); + }); + + describe("when using keyboard shortcut to reopen in container", function () { + beforeEach(async function () { + // Simulate the keyboard shortcut command + await this.webExt.background.browser.commands.onCommand.addListener.firstCall.args[0]("reopen_in_container_0"); + }); + + it("should open the page in the assigned container and close the original tab", async function () { + this.webExt.background.browser.tabs.create.should.have.been.calledWithMatch({ + url: "https://example.com", + cookieStoreId: "firefox-container-1", + index: 1, + active: true + }); + + this.webExt.background.browser.tabs.remove.should.have.been.called; + }); + }); + + describe("when container is set to 'none'", function () { + beforeEach(async function () { + await this.webExt.background.browser.commands.onCommand.addListener.firstCall.args[0]("reopen_in_container_9"); + }); + + it("should not reopen the tab", function () { + this.webExt.background.browser.tabs.create.should.not.have.been.called; + this.webExt.background.browser.tabs.remove.should.not.have.been.called; + }); + }); +}); \ No newline at end of file From 81ee998a57515d214638b8dddec767c8054c2de1 Mon Sep 17 00:00:00 2001 From: Anton Dudakov Date: Tue, 15 Jul 2025 08:42:37 +0200 Subject: [PATCH 2/3] extracted reopenInContainer function which made it possible to remove async from the `init()` --- src/_locales | 2 +- src/js/background/backgroundLogic.js | 33 +++++++++++++++------------- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/src/_locales b/src/_locales index bdaa012..4f5188f 160000 --- a/src/_locales +++ b/src/_locales @@ -1 +1 @@ -Subproject commit bdaa01291b7367a5e815470fd263ea36c862fe32 +Subproject commit 4f5188f3ba55916db3d74345abbbe651e2e8be78 diff --git a/src/js/background/backgroundLogic.js b/src/js/background/backgroundLogic.js index 3e7cddc..f2ff7d3 100644 --- a/src/js/background/backgroundLogic.js +++ b/src/js/background/backgroundLogic.js @@ -14,7 +14,7 @@ const backgroundLogic = { NUMBER_OF_KEYBOARD_SHORTCUTS: 10, unhideQueue: [], - async init() { + init() { browser.commands.onCommand.addListener(async function (command) { if (command === "sort_tabs") { backgroundLogic.sortTabs(); @@ -36,19 +36,7 @@ const backgroundLogic = { } if (command === reopenKey) { - const currentTab = await browser.tabs.query({active: true, currentWindow: true}); - if (currentTab.length > 0) { - const tab = currentTab[0]; - - await browser.tabs.create({ - url: tab.url, - cookieStoreId: cookieStoreId, - index: tab.index + 1, - active: tab.active - }); - - await browser.tabs.remove(tab.id); - } + backgroundLogic.reopenInContainer(cookieStoreId); return; } } @@ -88,12 +76,27 @@ const backgroundLogic = { browser.commands.reset("sort_tabs"); } } + + async reopenInContainer(cookieStoreId) { + const currentTab = await browser.tabs.query({ active: true, currentWindow: true }) + + if (currentTab.length > 0) { + const tab = currentTab[0]; + + browser.tabs.create({ + url: tab.url, + cookieStoreId: cookieStoreId, + index: tab.index + 1, + active: tab.active + }); + + browser.tabs.remove(tab.id); } }, updateTranslationInManifest() { for (let index = 0; index < 10; index++) { - const adjustedIndex = index + 1; + const adjustedIndex = index + 1; // We want to start from 1 instead of 0 in the UI. browser.commands.update({ name: `open_container_${index}`, description: browser.i18n.getMessage("containerShortcut", `${adjustedIndex}`) From f54b6afc02677d3a36355cbe5b8a20723a60bb4a Mon Sep 17 00:00:00 2001 From: Anton Dudakov Date: Tue, 15 Jul 2025 10:38:52 +0200 Subject: [PATCH 3/3] fixes merge conflicts --- src/_locales | 2 +- src/js/background/backgroundLogic.js | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/_locales b/src/_locales index 4f5188f..7ae3edd 160000 --- a/src/_locales +++ b/src/_locales @@ -1 +1 @@ -Subproject commit 4f5188f3ba55916db3d74345abbbe651e2e8be78 +Subproject commit 7ae3edd7455fd776a25a1017c0dfac26b21d7950 diff --git a/src/js/background/backgroundLogic.js b/src/js/background/backgroundLogic.js index f2ff7d3..7816412 100644 --- a/src/js/background/backgroundLogic.js +++ b/src/js/background/backgroundLogic.js @@ -76,6 +76,8 @@ const backgroundLogic = { browser.commands.reset("sort_tabs"); } } + } + }, async reopenInContainer(cookieStoreId) { const currentTab = await browser.tabs.query({ active: true, currentWindow: true })