From 9b9ea392608d88241054273ff7b7c0e445456b8f Mon Sep 17 00:00:00 2001 From: Anton Bershanskiy <8knots@protonmail.com> Date: Wed, 25 May 2022 00:13:02 +0300 Subject: [PATCH 1/2] Use History API when available --- src/background.ts | 35 ++++++++++++++++++++++++++++------- src/config.ts | 10 +++++++++- src/content.ts | 15 +++++++++++++++ 3 files changed, 52 insertions(+), 8 deletions(-) diff --git a/src/background.ts b/src/background.ts index 5a7bacd5..d17c1e16 100644 --- a/src/background.ts +++ b/src/background.ts @@ -23,14 +23,35 @@ if (utils.isFirefox()) { }); } -chrome.tabs.onUpdated.addListener(function(tabId) { - chrome.tabs.sendMessage(tabId, { +function onTabUpdatedListener(tabId: number) { + chrome.tabs.sendMessage(tabId, { message: 'update', - }, () => void chrome.runtime.lastError ); // Suppress error on Firefox -}); + }, () => void chrome.runtime.lastError ); // Suppress error on Firefox +} -chrome.runtime.onMessage.addListener(function (request, sender, callback) { - switch(request.message) { +function onNavigationApiAvailableChange(changes: {[key: string]: chrome.storage.StorageChange}) { + if (changes.navigationApiAvailable) { + if (changes.navigationApiAvailable.newValue) { + chrome.tabs.onUpdated.removeListener(onTabUpdatedListener); + } else { + chrome.tabs.onUpdated.addListener(onTabUpdatedListener); + } + } +} + +// If Navigation API is not supported, then background has to inform content script about video change. +// This happens on Safari, Firefox, and Chromium 101 (inclusive) and below. +utils.wait(() => Config.local !== null).then(() => { + if (!Config.local.navigationApiAvailable) + chrome.tabs.onUpdated.addListener(onTabUpdatedListener); +}) + +if (!Config.configSyncListeners.includes(onNavigationApiAvailableChange)) { + Config.configSyncListeners.push(onNavigationApiAvailableChange); +} + +chrome.runtime.onMessage.addListener(function (request, _, callback) { + switch(request.message) { case "openConfig": chrome.tabs.create({url: chrome.runtime.getURL('options/options.html' + (request.hash ? '#' + request.hash : ''))}); return; @@ -61,7 +82,7 @@ chrome.runtime.onMessage.addListener(function (request, sender, callback) { case "unregisterContentScript": unregisterFirefoxContentScript(request.id) return false; - } + } }); //add help page on install diff --git a/src/config.ts b/src/config.ts index 5a0fe5be..14034f09 100644 --- a/src/config.ts +++ b/src/config.ts @@ -101,9 +101,11 @@ export type VideoDownvotes = { segments: { uuid: HashedValue, hidden: SponsorHid interface SBStorage { /* VideoID prefixes to UUID prefixes */ downvotedSegments: Record, + navigationApiAvailable: boolean, } export interface SBObject { + configLocalListeners: Array<(changes: StorageChangesObject) => unknown>; configSyncListeners: Array<(changes: StorageChangesObject) => unknown>; syncDefaults: SBConfig; localDefaults: SBStorage; @@ -120,6 +122,7 @@ const Config: SBObject = { /** * Callback function when an option is updated */ + configLocalListeners: [], configSyncListeners: [], syncDefaults: { userID: null, @@ -283,7 +286,8 @@ const Config: SBObject = { } }, localDefaults: { - downvotedSegments: {} + downvotedSegments: {}, + navigationApiAvailable: null, }, cachedSyncConfig: null, cachedLocalStorage: null, @@ -310,6 +314,10 @@ function configProxy(): { sync: SBConfig, local: SBStorage } { for (const key in changes) { Config.cachedLocalStorage[key] = changes[key].newValue; } + + for (const callback of Config.configLocalListeners) { + callback(changes); + } } }); diff --git a/src/content.ts b/src/content.ts index fd842ef4..af5715f6 100644 --- a/src/content.ts +++ b/src/content.ts @@ -2204,3 +2204,18 @@ function checkForPreloadedSegment() { Config.forceSyncUpdate("unsubmittedSegments"); } } + +// Register listener for URL change via Navigation API +const navigationApiAvailable = "navigation" in window; +if (navigationApiAvailable) { + // TODO: Remove type cast once type declarations are updated + (window as unknown as { navigation: EventTarget }).navigation.addEventListener("navigate", () => videoIDChange(getYouTubeVideoID(document))); +} + +// Record availability of Navigation API +utils.wait(() => Config.local !== null).then(() => { + if (Config.local.navigationApiAvailable !== navigationApiAvailable) { + Config.local.navigationApiAvailable = navigationApiAvailable; + Config.forceLocalUpdate("navigationApiAvailable"); + } +}); From 7e5130c49a90f88ee1ebfda3776052f8fa93c2a4 Mon Sep 17 00:00:00 2001 From: Ajay Date: Thu, 2 Jun 2022 01:43:31 -0400 Subject: [PATCH 2/2] Don't wait to add listener --- src/background.ts | 8 +++++--- src/config.ts | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/background.ts b/src/background.ts index d17c1e16..d576fba1 100644 --- a/src/background.ts +++ b/src/background.ts @@ -41,10 +41,12 @@ function onNavigationApiAvailableChange(changes: {[key: string]: chrome.storage. // If Navigation API is not supported, then background has to inform content script about video change. // This happens on Safari, Firefox, and Chromium 101 (inclusive) and below. +chrome.tabs.onUpdated.addListener(onTabUpdatedListener); utils.wait(() => Config.local !== null).then(() => { - if (!Config.local.navigationApiAvailable) - chrome.tabs.onUpdated.addListener(onTabUpdatedListener); -}) + if (Config.local.navigationApiAvailable) { + chrome.tabs.onUpdated.removeListener(onTabUpdatedListener); + } +}); if (!Config.configSyncListeners.includes(onNavigationApiAvailableChange)) { Config.configSyncListeners.push(onNavigationApiAvailableChange); diff --git a/src/config.ts b/src/config.ts index 14034f09..fbb7ece7 100644 --- a/src/config.ts +++ b/src/config.ts @@ -287,7 +287,7 @@ const Config: SBObject = { }, localDefaults: { downvotedSegments: {}, - navigationApiAvailable: null, + navigationApiAvailable: null }, cachedSyncConfig: null, cachedLocalStorage: null,