diff --git a/manifests/chrome.json b/manifests/chrome.json index 8b3e76a..46d9269 100644 --- a/manifests/chrome.json +++ b/manifests/chrome.json @@ -2,13 +2,7 @@ "name": "YouTube Auto Pause", "version": "1.9.2", "description": "Stops YouTube (+ other video services) on tab unfocus and continues on focus", - "permissions": [ - "tabs", - "storage", - "activeTab", - "scripting", - "idle" - ], + "permissions": ["tabs", "storage", "activeTab", "scripting", "idle"], "host_permissions": [ "https://*.youtube.com/*", "https://*.vimeo.com/*", @@ -44,9 +38,7 @@ "service_worker": "yt.js" }, "externally_connectable": { - "ids": [ - "*" - ], + "ids": ["*"], "matches": [ "https://*.youtube.com/*", "https://*.youtubekids.com/*", @@ -65,7 +57,14 @@ "default": "Ctrl+Shift+K", "mac": "Command+Shift+K" }, - "description": "Toggle auto pause/resume" + "description": "Disable/enable extension" + }, + "toggle-tab": { + "suggested_key": { + "default": "Ctrl+Shift+L", + "mac": "Command+Shift+L" + }, + "description": "Disable/enable on active tab" }, "toggle-play": { "suggested_key": { diff --git a/manifests/firefox.json b/manifests/firefox.json index 3d2ffc8..33943fe 100644 --- a/manifests/firefox.json +++ b/manifests/firefox.json @@ -51,6 +51,13 @@ }, "description": "Toggle auto pause/resume" }, + "toggle-tab": { + "suggested_key": { + "default": "Ctrl+Shift+L", + "mac": "Command+Shift+L" + }, + "description": "Disable/enable on active tab" + }, "toggle-play": { "suggested_key": { "default": "Ctrl+Shift+Space", diff --git a/src/manifest.json b/src/manifest.json index 8b3e76a..46d9269 100644 --- a/src/manifest.json +++ b/src/manifest.json @@ -2,13 +2,7 @@ "name": "YouTube Auto Pause", "version": "1.9.2", "description": "Stops YouTube (+ other video services) on tab unfocus and continues on focus", - "permissions": [ - "tabs", - "storage", - "activeTab", - "scripting", - "idle" - ], + "permissions": ["tabs", "storage", "activeTab", "scripting", "idle"], "host_permissions": [ "https://*.youtube.com/*", "https://*.vimeo.com/*", @@ -44,9 +38,7 @@ "service_worker": "yt.js" }, "externally_connectable": { - "ids": [ - "*" - ], + "ids": ["*"], "matches": [ "https://*.youtube.com/*", "https://*.youtubekids.com/*", @@ -65,7 +57,14 @@ "default": "Ctrl+Shift+K", "mac": "Command+Shift+K" }, - "description": "Toggle auto pause/resume" + "description": "Disable/enable extension" + }, + "toggle-tab": { + "suggested_key": { + "default": "Ctrl+Shift+L", + "mac": "Command+Shift+L" + }, + "description": "Disable/enable on active tab" }, "toggle-play": { "suggested_key": { diff --git a/src/options.html b/src/options.html index f324b2e..719bc61 100644 --- a/src/options.html +++ b/src/options.html @@ -102,6 +102,7 @@

Settings

+ diff --git a/src/options.js b/src/options.js index e6d2350..40a6ad9 100644 --- a/src/options.js +++ b/src/options.js @@ -22,30 +22,49 @@ for (const host of hosts) { } // Saves options to chrome storage -function save_options() { +async function save_options() { const storage = {}; for (const option in options) { storage[option] = document.getElementById(option).checked; } - - env.storage.sync.set(storage, function () {}); + await env.storage.sync.set(storage); + + const disabledForActive = document.getElementById("disabledTabs").checked; + const tabs = await env.tabs.query({ active: true, currentWindow: true }); + const disabled = + (await env.storage.local.get("disabledTabs")).disabledTabs ?? []; + if (disabledForActive) { + await env.storage.local.set({ + disabledTabs: [...new Set([...disabled, tabs[0].id])], + }); + } else { + await env.storage.local.set({ + disabledTabs: disabled.filter((tab) => tab !== tabs[0].id), + }); + } } // Restores options from chrome storage -function restore_options() { - env.storage.sync.get(options, function (items) { - for (const opt in items) { - document.getElementById(opt).checked = items[opt]; - } +async function restore_options() { + const items = await env.storage.sync.get(options); + for (const opt in items) { + document.getElementById(opt).checked = items[opt]; + } - for (const option in options) { - document.getElementById(option).disabled = items.disabled; - if (items.disabled) { - document.getElementById("disabled").disabled = false; - } + for (const option in options) { + document.getElementById(option).disabled = items.disabled; + if (items.disabled) { + document.getElementById("disabled").disabled = false; } - }); + } + + const disabled = + (await env.storage.local.get("disabledTabs")).disabledTabs ?? []; + const tabs = await env.tabs.query({ active: true, currentWindow: true }); + if (disabled.includes(tabs[0].id)) { + document.getElementById("disabledTabs").checked = true; + } } // Show shortcuts in the options window @@ -92,14 +111,19 @@ version.textContent = "v" + env.runtime.getManifest().version; // Restore options on load and when they change in the store document.addEventListener("DOMContentLoaded", restore_options); -env.storage.onChanged.addListener(function (_changes, _namespace) { - restore_options(); +env.storage.onChanged.addListener(async (_changes, _namespace) => { + await restore_options(); }); // Listen to changes of options for (const option in options) { - document.getElementById(option).addEventListener("change", save_options); + document + .getElementById(option) + .addEventListener("change", async () => await save_options()); } +document + .getElementById("disabledTabs") + .addEventListener("change", async () => await save_options()); const coll = document.getElementsByClassName("collapsible_button"); let i; @@ -115,8 +139,3 @@ for (i = 0; i < coll.length; i++) { } }); } - -// Add event listener for the cursor tracking option -document - .getElementById("cursorTracking") - .addEventListener("change", save_options); diff --git a/src/yt.js b/src/yt.js index 42ce47d..70b2e32 100644 --- a/src/yt.js +++ b/src/yt.js @@ -5,7 +5,7 @@ const env = chrome.runtime ? chrome : browser; let previous_tab = -1; let previous_window = env.windows.WINDOW_ID_NONE; let executedTabs = []; -let enabledTabs = []; +let disabledTabs = []; // Computer state let state = "active"; @@ -29,35 +29,43 @@ for (const host of hosts) { options[host] = true; } +function debugLog(message) { + if (options.debugMode) { + console.log(`YouTube auto pause: ${message}`); + } +} + // Initialize settings from storage refresh_settings(); -function refresh_settings() { - env.storage.sync.get(Object.keys(options), function (result) { - options = Object.assign(options, result); - if (options.disabled === true) { - options.autopause = false; - options.autoresume = false; - options.scrollpause = false; - options.lockpause = false; - options.lockresume = false; - options.focuspause = false; - options.focusresume = false; - options.cursorTracking = false; - options.debugMode = false; - options.disableOnFullscreen = true; - for (var host of hosts) { - options[host] = false; - } +async function refresh_settings() { + const result = await env.storage.sync.get(Object.keys(options)); + options = Object.assign(options, result); + debugLog(`Settings refreshed: ${JSON.stringify(options)}`); + if (options.disabled === true) { + options.autopause = false; + options.autoresume = false; + options.scrollpause = false; + options.lockpause = false; + options.lockresume = false; + options.focuspause = false; + options.focusresume = false; + options.cursorTracking = false; + options.debugMode = false; + options.disableOnFullscreen = true; + for (const host of hosts) { + options[host] = false; } - enabledTabs = []; - }); + } + + disabledTabs = + (await env.storage.local.get("disabledTabs")).disabledTabs ?? []; + debugLog(`Disabled tabs: ${JSON.stringify(disabledTabs)}`); } -function debugLog(message) { - if (options.debugMode) { - console.log(`YouTube auto pause: ${message}`); - } +async function save_settings() { + await env.storage.sync.set(options); + await env.storage.local.set({ disabledTabs }); } function isEnabledForTab(tab) { @@ -65,8 +73,8 @@ function isEnabledForTab(tab) { return false; } - if (enabledTabs.includes(tab.id)) { - return true; + if (disabledTabs.includes(tab.id)) { + return false; } const optionKey = Object.keys(options).find((option) => { @@ -171,14 +179,8 @@ function changeIcon(disabled) { } // Listen options changes -env.storage.onChanged.addListener(async function (changes) { - enabledTabs = []; - for (const key in changes) { - debugLog( - `Settings changed for key ${key} from ${changes[key].oldValue} to ${changes[key].newValue}` - ); - options[key] = changes[key].newValue; - } +env.storage.onChanged.addListener(async function () { + await refresh_settings(); const tabs = await env.tabs.query({ active: true }); @@ -193,29 +195,33 @@ env.storage.onChanged.addListener(async function (changes) { }); // Tab change listener -env.tabs.onActivated.addListener(function (info) { - env.tabs.get(info.tabId, async function (tab) { - changeIcon(!isEnabledForTab(tab)); - if (!isEnabledForTab(tab) || previous_tab === info.tabId) { - return; - } +env.tabs.onActivated.addListener(async function (info) { + const tab = await env.tabs.get(info.tabId); + if (!tab) { + return; + } - await injectScript(tab); + changeIcon(!isEnabledForTab(tab)); + if (!isEnabledForTab(tab) || previous_tab === info.tabId) { + return; + } - if (options.autopause && previous_tab !== -1) { - debugLog(`Tab changed, stopping video from tab ${previous_tab}`); - env.tabs.get(previous_tab, function (prev) { - stop(prev); - }); - } + await injectScript(tab); - if (options.autoresume) { - debugLog(`Tab changed, resuming video from tab ${info.tabId}`); - resume(tab); + if (options.autopause && previous_tab !== -1) { + debugLog(`Tab changed, stopping video from tab ${previous_tab}`); + const prev = await env.tabs.get(previous_tab); + if (prev) { + stop(prev); } + } - previous_tab = info.tabId; - }); + if (options.autoresume) { + debugLog(`Tab changed, resuming video from tab ${info.tabId}`); + resume(tab); + } + + previous_tab = info.tabId; }); // Tab update listener @@ -245,14 +251,14 @@ env.tabs.onUpdated.addListener(async function (tabId, changeInfo, tab) { }); env.tabs.onRemoved.addListener(function (tabId) { - if (enabledTabs.includes(tabId)) { - debugLog(`Tab removed, removing tab ${tabId} from enabled tabs`); - enabledTabs = enabledTabs.filter((e) => e !== tabId); - } if (executedTabs.includes(tabId)) { debugLog(`Tab removed, removing tab ${tabId} from executed tabs`); executedTabs = executedTabs.filter((e) => e !== tabId); } + if (disabledTabs.includes(tabId)) { + disabledTabs = disabledTabs.filter((tab) => tab !== tabId); + save_settings(); + } }); // Window focus listener @@ -346,7 +352,18 @@ env.commands.onCommand.addListener(async (command) => { `Toggle extension command received, extension state ${options.disabled}` ); env.storage.sync.set({ disabled: options.disabled }); - refresh_settings(); + await refresh_settings(); + } else if (command === "toggle-tab") { + const tabs = await env.tabs.query({ active: true, currentWindow: true }); + const tab = tabs[0]; + debugLog(`Toggle tab command received for tab ${tab.id}`); + if (disabledTabs.includes(tab.id)) { + disabledTabs = disabledTabs.filter((t) => t !== tab.id); + } else { + disabledTabs.push(tab.id); + } + await save_settings(); + changeIcon(!isEnabledForTab); } else if (command === "toggle-play") { debugLog( `Toggle play command received, toggling play for all tabs in current window`