diff --git a/_locales/de/messages.json b/_locales/de/messages.json index a0d80da..0cd4078 100644 --- a/_locales/de/messages.json +++ b/_locales/de/messages.json @@ -14,5 +14,25 @@ "optionActiveWindow": { "message": "Halte das aktive Fenster am Leben", "description": "Label for option for whether to put tabs to sleep in the active window." + }, + "menuGroup": { + "message": "Dormancy - 'Einschläfern' von Tabs", + "description": "Menu group for the extension at tab context." + }, + "menuDiscardSelected": { + "message": "Au&sgewählte Tabs 'einschläfern'", + "description": "Menu item to put all selected / highlighted tabs to sleep." + }, + "menuDiscardLeft": { + "message": "Tabs &links 'einschläfern'", + "description": "Menu item to put tabs to the left in the same window to sleep." + }, + "menuDiscardRight": { + "message": "Tabs &rechts 'einschläfern'", + "description": "Menu item to put tabs to the right in the same window to sleep." + }, + "menuDiscardOther": { + "message": "&Andere Tabs im Fenster 'einschläfern'", + "description": "Menu item to put all other tabs in the same window to sleep." } } diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 8a6a7a6..a8fbcd5 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -18,5 +18,25 @@ "optionExcludedWebsites": { "message": "Keep these URLs alive (separated by commas)", "description": "Comma separated list of website URLs." + }, + "menuGroup": { + "message": "Dormancy - Put tabs to sleep", + "description": "Menu group for the extension at tab context." + }, + "menuDiscardSelected": { + "message": "Put &selected tabs to sleep", + "description": "Menu item to put all selected / highlighted tabs to sleep." + }, + "menuDiscardLeft": { + "message": "Put tabs to the &left to sleep", + "description": "Menu item to put tabs to the left in the same window to sleep." + }, + "menuDiscardRight": { + "message": "Put tabs to the &right to sleep", + "description": "Menu item to put tabs to the right in the same window to sleep." + }, + "menuDiscardOther": { + "message": "Put &other tabs of window to sleep", + "description": "Menu item to put all other tabs in the same window to sleep." } } diff --git a/background.js b/background.js index a7ca1ff..977b414 100644 --- a/background.js +++ b/background.js @@ -45,22 +45,23 @@ return config.excludedWebsites.value.some(w => w.length && url.startsWith(w)); } - // Check for tabs that have hit dormanticizable age and dormanticize them. + const tabQueryOptions = { + // keep tabs that play sound awake + audible: false, + // discarded tabs are already asleep, ignore them + discarded: false, + // keep pinned tabs awake for their special role + pinned: false, + } + + // Check for tabs that have hit sleeping age and put them to sleep. async function periodicTabCheck() { // Query for the active tab let activeWindow = await browser.windows.getCurrent(); let activeWindowId = activeWindow.id; // Query for all tabs that are not the active tab - let tabs = await browser.tabs.query({ - pinned: false, - // only sleep if isn't the active tab - active: false, - // only sleep if not already asleep - discarded: false, - // do not sleep tabs that play sound - audible: false - }); + let tabs = await browser.tabs.query({ ...tabQueryOptions, active: false }); for (let i in tabs) { let tab = tabs[i]; @@ -87,12 +88,88 @@ } }); + function addMenu() { + + async function discardTabs(tabs) { + tabs.forEach(tab => { + if (!tab.active) { + browser.tabs.discard(tab.id); + } + }); + } + async function discardSelected() { + let tabs = await browser.tabs.query({ ...tabQueryOptions, currentWindow: true, highlighted: true }); + discardTabs(tabs); + }; + async function getCurrentWindowsTabs() { + return await browser.tabs.query({ ...tabQueryOptions, currentWindow: true }); + } + async function discardPositional(position) { + let tabs = await getCurrentWindowsTabs(); + const toDiscard = [] + if (position != 'left') { + tabs = tabs.reverse(); + } + for (let i = 0; !tabs[i].active && i < tabs.length; i++) { + toDiscard.push(tabs[i]) + } + discardTabs(toDiscard); + }; + async function discardLeft() { + discardPositional('left'); + } + async function discardRight() { + discardPositional('right'); + } + async function discardOther() { + let tabs = await getCurrentWindowsTabs(); + discardTabs(tabs); + } + + browser.menus.remove('dormancy-menu'); + const topMenuId = browser.menus.create({ + id: 'dormancy-menu', + title: browser.i18n.getMessage('menuGroup'), + icons: { + '96': 'icon-96.png' + }, + contexts: ['tab'] + }); + browser.menus.create({ + id: 'dormancy-menu-discard-selected', + parentId: topMenuId, + title: browser.i18n.getMessage('menuDiscardSelected'), + onclick: discardSelected + }); + browser.menus.create({ + id: 'dormancy-menu-discard-left', + parentId: topMenuId, + title: browser.i18n.getMessage('menuDiscardLeft'), + onclick: discardLeft + }); + browser.menus.create({ + id: 'dormancy-menu-discard-right', + parentId: topMenuId, + title: browser.i18n.getMessage('menuDiscardRight'), + onclick: discardRight + }); + browser.menus.create({ + id: 'dormancy-menu-discard-other', + parentId: topMenuId, + title: browser.i18n.getMessage('menuDiscardOther'), + onclick: discardOther + }); + }; + // Start everything. Or cancel what's going on and restart. async function init() { // Load (or reload) config from storage let oldConfig = config; config = await loadConfig(); + // add a context menu to tab-strip to put tabs to sleep manually + addMenu(); + // Reset timer if timeout value changed if (!timerId || (oldConfig.timeout.value && (config.timeout.value != oldConfig.timeout.value))) { if (timerId) { diff --git a/manifest.json b/manifest.json index ded63b7..1056bd7 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,10 @@ { "name": "__MSG_extensionName__", "description": "__MSG_extensionDescription__", - "version": "3.4.3", + "icons": { + "96": "icon-96.png" + }, + "version": "3.5.0", "manifest_version": 2, "default_locale": "en", @@ -25,6 +28,7 @@ }, "permissions": [ + "menus", "sessions", "storage", "tabs"