From 06e3ee9c88b96a7f65734760d0702d64fae01d1c Mon Sep 17 00:00:00 2001 From: fire332 <96039230+fire332@users.noreply.github.com> Date: Thu, 19 Dec 2024 00:43:30 -0800 Subject: [PATCH] clean up code and add config --- src/config.js | 1 + src/thumbnail-quality.ts | 44 +++++++++++++++++++++++++--------------- src/ui.js | 1 + 3 files changed, 30 insertions(+), 16 deletions(-) diff --git a/src/config.js b/src/config.js index 8cbece95..bf2313f1 100644 --- a/src/config.js +++ b/src/config.js @@ -2,6 +2,7 @@ const CONFIG_KEY = 'ytaf-configuration'; const configOptions = new Map([ ['enableAdBlock', { default: true, desc: 'Enable ad blocking' }], + ['upgradeThumbnails', { default: false, desc: 'Upgrade thumbnail quality' }], [ 'removeShorts', { default: false, desc: 'Remove Shorts from subscriptions' } diff --git a/src/thumbnail-quality.ts b/src/thumbnail-quality.ts index fc036e31..f0790e1f 100644 --- a/src/thumbnail-quality.ts +++ b/src/thumbnail-quality.ts @@ -38,8 +38,7 @@ function rewriteURL(url: URL) { const YT_THUMBNAIL_PATHNAME_REGEX = /vi(?:_webp)?(\/.*?\/)([a-z0-9]+?)(_\w*?)?\.[a-z]+$/g; - const YT_THUMBNAIL_NAMES = [ - 'maxresdefault', + const YT_TARGET_THUMBNAIL_NAMES = [ 'sddefault', 'hqdefault', 'mqdefault', @@ -53,8 +52,8 @@ function rewriteURL(url: URL) { const replacementPathname = url.pathname.replace( YT_THUMBNAIL_PATHNAME_REGEX, (match, p1, p2, p3) => { - if (!YT_THUMBNAIL_NAMES.includes(p2)) return match; // Only rewrite regular thumbnail URLs. Not shorts, etc. - return `${webpSupported ? 'vi_webp' : 'vi'}${p1}maxresdefault${p3 ?? ''}.${webpSupported ? 'webp' : 'jpg'}`; + if (!YT_TARGET_THUMBNAIL_NAMES.includes(p2)) return match; // Only rewrite regular thumbnail URLs. Not shorts, etc. + return `${webpSupported ? 'vi_webp' : 'vi'}${p1}sddefault${p3 ?? ''}.${webpSupported ? 'webp' : 'jpg'}`; } ); if (url.pathname === replacementPathname) @@ -73,7 +72,7 @@ function parseCSSUrl(value: string) { return new URL(value.slice(4, -1).replace(/["']/g, '')); } -function upgradeBgImg(element: HTMLElement) { +async function upgradeBgImg(element: HTMLElement) { const style = element.style; const old = parseCSSUrl(style.backgroundImage); @@ -82,9 +81,11 @@ function upgradeBgImg(element: HTMLElement) { const lazyLoader = new Image(); - console.log('Upgrading', element, target.href); - lazyLoader.onload = () => { + // Don't swap if a placeholder thumbnail was provided. + // Placeholder thumbnails are the same size as the "default" size. + if (lazyLoader.naturalHeight === 90) return; + const curr = parseCSSUrl(style.backgroundImage); // Don't swap out element image if it has been changed while target image was loading. @@ -96,12 +97,13 @@ function upgradeBgImg(element: HTMLElement) { lazyLoader.src = target.href; } -const YT_THUMBNAIL_ELEMENT_TAG = 'ytlr-thumbnail-details'; - const obs = new MutationObserver((mutations) => { + const YT_THUMBNAIL_ELEMENT_TAG = 'ytlr-thumbnail-details'; + const dummy = document.createElement('div'); // handle backgroundImage change + // YT re-uses thumbnail elements in its virtual list implementation. mutations .filter((mut) => mut.type === 'attributes') .map((mut) => [mut.target, mut] as const) @@ -131,10 +133,20 @@ const obs = new MutationObserver((mutations) => { .forEach(upgradeBgImg); }); -obs.observe(document.body, { - subtree: true, - childList: true, - attributes: true, - attributeFilter: ['style'], - attributeOldValue: true -}); +function enableObserver() { + obs.observe(document.body, { + subtree: true, + childList: true, + attributes: true, + attributeFilter: ['style'], + attributeOldValue: true + }); +} + +import { configRead, configAddChangeListener } from './config'; + +if (configRead('upgradeThumbnails')) enableObserver(); + +configAddChangeListener('upgradeThumbnails', (value) => + value ? enableObserver() : obs.disconnect() +); diff --git a/src/ui.js b/src/ui.js index 0cb85d43..8702b853 100644 --- a/src/ui.js +++ b/src/ui.js @@ -120,6 +120,7 @@ function createOptionsPanel() { elmContainer.appendChild(elmHeading); elmContainer.appendChild(createConfigCheckbox('enableAdBlock')); + elmContainer.appendChild(createConfigCheckbox('upgradeThumbnails')); elmContainer.appendChild(createConfigCheckbox('hideLogo')); elmContainer.appendChild(createConfigCheckbox('removeShorts')); elmContainer.appendChild(createConfigCheckbox('enableSponsorBlock'));