Skip to content

Commit

Permalink
feat: allow enabling/disabling for single tab
Browse files Browse the repository at this point in the history
  • Loading branch information
drodil committed Oct 7, 2024
1 parent 79219a0 commit 4c5ec50
Show file tree
Hide file tree
Showing 6 changed files with 143 additions and 101 deletions.
21 changes: 10 additions & 11 deletions manifests/chrome.json
Original file line number Diff line number Diff line change
Expand Up @@ -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/*",
Expand Down Expand Up @@ -44,9 +38,7 @@
"service_worker": "yt.js"
},
"externally_connectable": {
"ids": [
"*"
],
"ids": ["*"],
"matches": [
"https://*.youtube.com/*",
"https://*.youtubekids.com/*",
Expand All @@ -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": {
Expand Down
7 changes: 7 additions & 0 deletions manifests/firefox.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
21 changes: 10 additions & 11 deletions src/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -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/*",
Expand Down Expand Up @@ -44,9 +38,7 @@
"service_worker": "yt.js"
},
"externally_connectable": {
"ids": [
"*"
],
"ids": ["*"],
"matches": [
"https://*.youtube.com/*",
"https://*.youtubekids.com/*",
Expand All @@ -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": {
Expand Down
1 change: 1 addition & 0 deletions src/options.html
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ <h4>Settings</h4>
<label><input type="checkbox" id="scrollpause"><span class="label-text">Enable auto pause when out of viewport</span></label>
<label><input type="checkbox" id="cursorTracking"><span class="label-text">Enable cursor on window tracking</span></label>
<label><input type="checkbox" id="manualPause"><span class="label-text">Manual pause disables auto resume</span></label>
<label><input type="checkbox" id="disabledTabs"><span class="label-text">Disable on this tab</span></label>
<label><input type="checkbox" id="disableOnFullscreen"><span class="label-text">Disable on full screen</span></label>
<label><input type="checkbox" id="disabled"><span class="label-text">Disable extension</span></label>
</div>
Expand Down
63 changes: 41 additions & 22 deletions src/options.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand All @@ -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);
131 changes: 74 additions & 57 deletions src/yt.js
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand All @@ -29,44 +29,52 @@ 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) {
if (!tab || !tab.url || options.disabled) {
return false;
}

if (enabledTabs.includes(tab.id)) {
return true;
if (disabledTabs.includes(tab.id)) {
return false;
}

const optionKey = Object.keys(options).find((option) => {
Expand Down Expand Up @@ -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 });

Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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`
Expand Down

0 comments on commit 4c5ec50

Please sign in to comment.