diff --git a/js&css/extension/init.js b/js&css/extension/init.js index bd08ec575..5d01285c7 100644 --- a/js&css/extension/init.js +++ b/js&css/extension/init.js @@ -183,33 +183,37 @@ document.addEventListener('it-message-from-youtube', function () { }); } } else if (message.action === 'blocklist') { - var type = message.type, - id = message.id, - title = message.title; - if (!extension.storage.data.blocklist || typeof extension.storage.data.blocklist !== 'object') { extension.storage.data.blocklist = {}; } - if (type === 'channel') { - if (!extension.storage.data.blocklist.channels) { - extension.storage.data.blocklist.channels = {}; - } - - extension.storage.data.blocklist.channels[id] = { - title: title, - preview: message.preview - }; - } - - if (type === 'video') { - if (!extension.storage.data.blocklist.videos) { - extension.storage.data.blocklist.videos = {}; - } - - extension.storage.data.blocklist.videos[id] = { - title: title - }; + switch(message.type) { + case 'channel': + if (!extension.storage.data.blocklist.channels) { + extension.storage.data.blocklist.channels = {}; + } + if (message.added) { + extension.storage.data.blocklist.channels[message.id] = { + title: message.title, + preview: message.preview + } + } else { + delete extension.storage.data.blocklist.channels[message.id]; + } + break + + case 'video': + if (!extension.storage.data.blocklist.videos) { + extension.storage.data.blocklist.videos = {}; + } + if (message.added) { + extension.storage.data.blocklist.videos[message.id] = { + title: message.title + } + } else { + delete extension.storage.data.blocklist.videos[message.id]; + } + break } chrome.storage.local.set({ @@ -241,4 +245,4 @@ document.addEventListener('it-play', function (event) { var videos = document.querySelectorAll('video'); try {chrome.runtime.sendMessage({action: 'play'})} catch(error){console.log(error); setTimeout(function () { try { chrome.runtime.sendMessage({action: 'play'}, function (response) { console.log(response) } ); } catch { } }, 321) } - }); \ No newline at end of file + }); diff --git a/js&css/extension/www.youtube.com/styles.css b/js&css/extension/www.youtube.com/styles.css index 860d07d1d..b772dcb56 100644 --- a/js&css/extension/www.youtube.com/styles.css +++ b/js&css/extension/www.youtube.com/styles.css @@ -1,7 +1,7 @@ /* fix for youtube's player moving in from the right side */ html {overflow-x: hidden !important} /* html {overflow-x: hidden !important} -/* Fix to tame Youtube's page-load / make it more calm - the player wont annoyingly slide in from the right anymore */ +/* Fix to tame Youtube's page-load / make it more calm - the player wont annoyingly slide in from the right anymore */ /* previously also: html[it-transcript='true'] {overflow-x: hidden !important}*/ @-moz-document url-prefix() {overflow-x: visible !important} /* REMOVE ME SOON https://github.com/code-charity/youtube/issues/1649 */ @@ -11,7 +11,7 @@ html {overflow-x: hidden !important} html[it-pathname*="/shorts/"] #content.style-scope ytd-engagement-panel-title-header-renderer { max-width: 42vw !important; } - /* or maybe something like : html[it-pathname*="/shorts/"] #header.style-scope ytd-engagement-panel-title-header-renderer "visibility-button" */ + /* or maybe something like : html[it-pathname*="/shorts/"] #header.style-scope ytd-engagement-panel-title-header-renderer "visibility-button" */ } /*------------------------------------------------------------------------------ @@ -57,27 +57,27 @@ html[it-ads=subscribed_channels] #related #player-ads, html[it-ads=subscribed_channels] #masthead-ad, html[it-ads=subscribed_channels] *[target-id*='engagement-panel-ads'], html[it-ads=subscribed_channels] .ytd-ad-slot-renderer, -html[it-ads=subscribed_channels] yt-mealbar-promo-renderer, -html[it-ads=subscribed_channels] #player .ytp-ad-image-overlay, +html[it-ads=subscribed_channels] yt-mealbar-promo-renderer, +html[it-ads=subscribed_channels] #player .ytp-ad-image-overlay, html[it-ads=subscribed_channels] #player .video-ads .ytp-ad-player-overlay-flyout-cta, html[it-ads=subscribed_channels] #player .ytp-ad-module .ytp-ad-player-overlay-flyout-cta, html[it-ads=block_all] #related #player-ads, html[it-ads=block_all] #masthead-ad, html[it-ads=block_all] *[target-id*='engagement-panel-ads'], -html[it-ads=block_all] .ytd-ad-slot-renderer, +html[it-ads=block_all] .ytd-ad-slot-renderer, html[it-ads=block_all] yt-mealbar-promo-renderer, html[it-ads=block_all] #player .ytp-ad-image-overlay, -html[it-ads=block_all] #player .video-ads .ytp-ad-player-overlay-flyout-cta, +html[it-ads=block_all] #player .video-ads .ytp-ad-player-overlay-flyout-cta, html[it-ads=block_all] #player .ytp-ad-module .ytp-ad-player-overlay-flyout-cta{ display: none !important; } /* -html[it-ads=subscribed_channels] #player .video-ads, -html[it-ads=subscribed_channels] #player .ytp-ad-module, -html[it-ads=block_all] #player .video-ads, +html[it-ads=subscribed_channels] #player .video-ads, +html[it-ads=subscribed_channels] #player .ytp-ad-module, +html[it-ads=block_all] #player .video-ads, html[it-ads=block_all] #player .ytp-ad-module { - opacity: 0.0001 !important; + opacity: 0.0001 !important; } html[it-ads=subscribed_channels] #player .ytp-ad-preview-image, @@ -194,20 +194,20 @@ html[it-mini-player-cursor='nw-resize']::after { /*------------------------------------------------------------------------------ -# +# ------------------------------------------------------------------------------*/ -html[data-page-type='video'][it-player-fit-to-win-button='true'] .ytp-right-controls { +html[it-player-fit-to-win-button=true][data-page-type=video] .ytp-right-controls { display: flex; } -html[data-page-type='video'][it-player-fit-to-win-button='true'] #it-fit-to-win-player-button { +html[it-player-fit-to-win-button=true][data-page-type=video] #it-fit-to-win-player-button { order: 1; } -html[data-page-type='video'][it-player-fit-to-win-button='true'] .ytp-fullscreen-button { +html[it-player-fit-to-win-button=true][data-page-type=video] .ytp-fullscreen-button { order: 2; } -html[data-page-type='video'][it-player-fit-to-win-button='true'] #ftw-icon path { +html[it-player-fit-to-win-button=true][data-page-type=video] #ftw-icon path { fill: none; } .it-player-button { @@ -454,7 +454,7 @@ ytd-guide-section-renderer .it-button::after { /*------------------------------------------------------------------------------ -9.0 BLACKLIST +9.0 BLOCKLIST ------------------------------------------------------------------------------*/ .it-add-to-blocklist { position: absolute; @@ -479,7 +479,7 @@ ytd-guide-section-renderer .it-button::after { align-items: center; content: 'Blocklist'; text-transform: uppercase; - color: white; /*quick-fix for: var(--yt-spec-icon-active-other, #fff);*/ + color: white; /*quick-fix for: var(--yt-spec-icon-active-other, #fff);*/ position: absolute; left: 100%; top: 0; @@ -530,35 +530,61 @@ ytd-guide-section-renderer .it-button::after { *:hover>.it-add-to-blocklist { visibility: visible; } -.it-blocklisted-video { + +.it-blocklisted-video .it-add-to-blocklist svg, +.it-blocklisted-channel .it-add-to-blocklist svg { + fill: green; +} + +.it-blocklisted-video .it-add-to-blocklist::after, +.it-blocklisted-channel .it-add-to-blocklist::after { + color: green; +} + +.it-blocklisted-video .it-add-to-blocklist::after { + content: "Unblock Video"; +} + +.it-blocklisted-channel .it-add-to-blocklist::after { + content: "Unblock Channel"!important; +} + +.it-blocklisted-video, +.it-blocklisted-channel { opacity: .15; - max-height: 19px; + max-height: 4rem; overflow: hidden; - margin-top: -5px !important; transition: max-height 0.4s ease 0.1s; } -.it-blocklisted-video ytd-thumbnail { + +ytd-grid-video-renderer .it-blocklisted-video, +ytd-grid-video-renderer .it-blocklisted-channel, +ytd-rich-grid-media .it-blocklisted-video, +ytd-rich-grid-media .it-blocklisted-channel { + overflow: visible; +} + +.it-blocklisted-video ytd-thumbnail, +.it-blocklisted-channel ytd-thumbnail { visibility: hidden; max-width: 0; transition: max-width 0.4s ease 0.1s; } -.it-blocklisted-video:hover { + +.it-blocklisted-video:hover, +.it-blocklisted-channel:hover { opacity: 1; overflow: visible; max-height: 120px; transition: max-height 0.4s ease 1.1s; } -.it-blocklisted-video:hover ytd-thumbnail { + +.it-blocklisted-video:hover ytd-thumbnail, +.it-blocklisted-channel:hover ytd-thumbnail { visibility: visible; max-width: 220px; transition: max-width 0.4s ease 1.1s; - margin-top: -7px !important; - margin-bottom: 4px !important; - margin-left: 5px !important; } -/* .it-blocklisted-video #metadata-line {display:none !important} - .it-blocklisted-video div {display: inline-block !important} */ - /*------------NEW---------------*/ .improvedtube-sidebar-a { @@ -633,7 +659,7 @@ ytd-guide-section-renderer .it-button::after { 3.0 THEMES ------------------------------------------------------------------------------*/ /*update: cinematics */ -html[it-theme=black] #cinematics, +html[it-theme=black] #cinematics, html[it-theme=desert] #cinematics { display:none !important } @@ -889,7 +915,7 @@ html[it-theme=black][data-system-color-scheme=light][it-schedule=system_peferenc } /*DAWN*/ - + html[it-theme=dawn] [dark], html[it-theme=dawn]:not([it-schedule=system_peference_dark]):not([it-schedule=system_peference_light]), html[it-theme=dawn][data-system-color-scheme=dark][it-schedule=system_peference_dark], @@ -1124,7 +1150,7 @@ html[it-theme=dawn][data-system-color-scheme=light][it-schedule=system_peference --yt-lightsource-secondary-title-color: var(--yt-spec-text-secondary) !important; } -/*DESERT*/ +/*DESERT*/ html[it-theme=desert]:not([it-schedule=system_peference_dark]):not([it-schedule=system_peference_light]), html[it-theme=desert][data-system-color-scheme=dark][it-schedule=system_peference_dark], @@ -1808,7 +1834,7 @@ html[it-theme=plain][data-system-color-scheme=light][it-schedule=system_peferenc /*SUNSET*/ - + html[it-theme=sunset] [dark], html[it-theme=sunset]:not([it-schedule=system_peference_dark]):not([it-schedule=system_peference_light]), html[it-theme=sunset][data-system-color-scheme=dark][it-schedule=system_peference_dark], diff --git a/js&css/web-accessible/core.js b/js&css/web-accessible/core.js index f48e49b04..04d0296df 100644 --- a/js&css/web-accessible/core.js +++ b/js&css/web-accessible/core.js @@ -27,7 +27,8 @@ var ImprovedTube = { comments: {}, collapse_of_subscription_sections: [], mark_watched_videos: [], - blocklist_buttons: [] + blocklist_buttons: [], + observerList: [] }, regex: { channel: /\/(@|c\/@?|channel\/|user\/)(?[^/]+)/, @@ -173,6 +174,9 @@ document.addEventListener('it-message-from-extension', function () { } ImprovedTube.init(); + // need to run blocklist once just after page load to catch initial nodes + ImprovedTube.blocklist(); + // REACTION OR VISUAL FEEDBACK WHEN THE USER CHANGES A SETTING (already automated for our CSS features): } else if (message.action === 'storage-changed') { var camelized_key = message.camelizedKey; @@ -354,10 +358,6 @@ document.addEventListener('it-message-from-extension', function () { ImprovedTube.playerRemainingDuration(); } break - - case 'blocklistActivate': - if (ImprovedTube.storage.blocklist_activate === true) {document.querySelectorAll('.it-add-to-blocklist').forEach(e => e.remove());} - break } if (ImprovedTube[camelized_key]) { diff --git a/js&css/web-accessible/functions.js b/js&css/web-accessible/functions.js index dc81cf4c8..9713f1c23 100644 --- a/js&css/web-accessible/functions.js +++ b/js&css/web-accessible/functions.js @@ -40,11 +40,8 @@ ImprovedTube.ytElementsHandler = function (node) { if (node.href) { this.channelDefaultTab(node); - if (node.className.indexOf('ytd-thumbnail') !== -1) { - this.blocklist('video', node); - } - if (node.href.match(/@|((channel|user|c)\/)([^/]+)/)) { - this.blocklist('channel', node); + if (this.storage.blocklist_activate && node.classList.contains('ytd-thumbnail')) { + this.blocklist('video', node); } } } /* else if (name === 'META') { // infos are not updated when clicking related videos... @@ -139,8 +136,8 @@ ImprovedTube.ytElementsHandler = function (node) { // } else if (name === 'YTD-PLAYLIST-HEADER-RENDERER' || (name === 'YTD-MENU-RENDERER' && node.classList.contains('ytd-playlist-panel-renderer'))) { this.playlistPopupUpdate(); - } else if (name === 'YTD-SUBSCRIBE-BUTTON-RENDERER') { - if (node.className.indexOf('ytd-c4-tabbed-header-renderer') !== -1) { + } else if (name === 'YTD-SUBSCRIBE-BUTTON-RENDERER' || name === 'YT-SUBSCRIBE-BUTTON-VIEW-MODEL') { + if (this.storage.blocklist_activate) { ImprovedTube.blocklist('channel', node); } @@ -458,6 +455,7 @@ ImprovedTube.onkeydown = function () { }; ImprovedTube.onmousedown = function (event) { + window.addEventListener('mousedown', function (event) { if (ImprovedTube.elements.player && ImprovedTube.elements.player.classList.contains('ad-showing') === false) { var path = event.composedPath(); @@ -470,6 +468,7 @@ ImprovedTube.onmousedown = function (event) { ImprovedTube.user_interacted = true; } } + } }, true); }; diff --git a/js&css/web-accessible/www.youtube.com/blocklist.js b/js&css/web-accessible/www.youtube.com/blocklist.js index 6fa0ea787..7a348daa1 100644 --- a/js&css/web-accessible/www.youtube.com/blocklist.js +++ b/js&css/web-accessible/www.youtube.com/blocklist.js @@ -1,187 +1,244 @@ /*------------------------------------------------------------------------------ 4.8.0 BLOCKLIST ------------------------------------------------------------------------------*/ +// usage: +// () called only to turn On (rescans all elements on page)/Off +// ('video', node) called only for 'a#thumbnail.ytd-thumbnail[href]' +// ('channel', node) called only for 'ytd-subscribe-button-renderer.ytd-c4-tabbed-header-renderer' ImprovedTube.blocklist = function (type, node) { + if (this.storage.blocklist_activate) { + if (type === 'video') { + if (node.nodeName !== 'A' || !node.href) { alert(1) }; + const video = node.href.match(ImprovedTube.regex.video_id)?.[1], + channel = node.parentNode.__dataHost?.__data?.data?.shortBylineText?.runs?.[0]?.navigationEndpoint?.commandMetadata?.webCommandMetadata?.url ? node.parentNode.__dataHost.__data.data.shortBylineText.runs[0].navigationEndpoint.commandMetadata.webCommandMetadata.url.match(ImprovedTube.regex.channel).groups.name : undefined; + let mode = 'video', + blockedElement; + if (!video) return; // no video ID, something went horribly wrong, bail + + // YT reuses VIDEO elements dynamically, need to monitor and also dynamically readjust BLOCK style + if (!this.elements.observerList.includes(node)) { + // YT reuses VIDEO elements dynamically, need to monitor and also dynamically readjust BLOCK style whenever href is modified + this.blocklistObserver.observe(node, {attributes: true, + attributeFilter: ['href']}); + // keep track to only attach one observer per element + this.elements.observerList.push(node); + } - if (this.storage.blocklist_activate !== true) { - // for (var i = 0, l = this.elements.blocklist_buttons.length; i < l; i++) { - // this.elements.blocklist_buttons[i].remove(); - return; - } else if (!node) { - var a = document.querySelectorAll('a.ytd-thumbnail'), - a2 = document.querySelectorAll('a[href*="/channel/"],a[href*="/user/"],a[href*="/c/"],a[href*="/@"]'), - subscribe_buttons = document.querySelectorAll('ytd-subscribe-button-renderer.ytd-c4-tabbed-header-renderer'); - - for (var i = 0, l = a.length; i < l; i++) { - this.blocklist('video', a[i]); - } - - for (var i = 0, l = subscribe_buttons.length; i < l; i++) { - this.blocklist('channel', subscribe_buttons[i]); - } - - for (var i = 0, l = a2.length; i < l; i++) { - this.blocklist('channel', a2[i]); - } - } - - if (!this.storage.blocklist || typeof this.storage.blocklist !== 'object') { - this.storage.blocklist = { - channels: {}, - videos: {} - }; - } + switch(node.parentNode.className.replace('style-scope ','')) { + case 'ytd-compact-video-renderer': + // list next to player + // node.parentNode.__dataHost.$.dismissible; + case 'ytd-rich-item-renderer': + // short reel + case 'ytd-rich-grid-media': + // grid reel + case 'ytd-rich-grid-slim-media': + // short grid reel + case 'ytd-playlist-video-renderer': + // playlist page + case 'ytd-playlist-panel-video-renderer': + // playlist next to player + // node.parentNode.closest('ytd-playlist-panel-video-renderer') + case 'ytd-structured-description-video-lockup-renderer': + // list under the player + // node.parentNode.closest('ytd-structured-description-video-lockup-renderer') + // or even node.parentNode.closest('ytd-compact-infocard-renderer') === node.parentNode.parentNode.parentNode.parentNode + blockedElement = node.parentNode.parentNode.parentNode; + break; + case 'ytd-grid-video-renderer': + // channel home screen grid + case 'ytd-reel-item-renderer': + // reel + blockedElement = node.parentNode.parentNode; + break; + } - if (!this.storage.blocklist.channels || typeof this.storage.blocklist.channels !== 'object') { - this.storage.blocklist.channels = {}; - } + if (!blockedElement) return; // couldnt find valid enveloping element, bail - if (!this.storage.blocklist.videos || typeof this.storage.blocklist.videos !== 'object') { - this.storage.blocklist.videos = {}; - } + node.blockedElement = blockedElement; - if (type === 'video') { - var id = node.href.match(ImprovedTube.regex.video_id); - // Hide blocklisted videos: - if (id && id[1] && ImprovedTube.storage.blocklist.videos[id[1]]) { - //node.__dataHost.classList.add('it-blocklisted-video'); // this only affects the thumbnail - const dismissibleElement = node.parentNode.__dataHost.$.dismissible; - if (dismissibleElement) { dismissibleElement.classList.add('it-blocklisted-video'); } // this affects the title and co. as well - // node.parentNode.parentNode.__dataHost.$.ytd-compact-video-renderer.classList.add('it-blocklisted-video'); - } + if (this.storage.blocklist.videos[video] && !blockedElement.classList.contains('it-blocklisted-video')) { + // blocklisted video + blockedElement.classList.add('it-blocklisted-video'); + } else if (!this.storage.blocklist.videos[video] && blockedElement.classList.contains('it-blocklisted-video')) { + // video not blocklisted, show it + blockedElement.classList.remove('it-blocklisted-video'); + } - // skip blocklist button creation, if it exists already: - if(node.getElementsByClassName("it-add-to-blocklist").length > 0){ - return - } - - var button = document.createElement('button'), - svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'), - path = document.createElementNS('http://www.w3.org/2000/svg', 'path'); - - button.className = 'it-add-to-blocklist'; - button.addEventListener('click', function (event) { - if (this.parentNode.href) { - var data = this.parentNode.__dataHost.__data, - id = this.parentNode.href.match(ImprovedTube.regex.video_id), - title = ''; - - if ( - data && - data.data && - data.data.title && - data.data.title.runs && - data.data.title.runs[0] - ) { - title = data.data.title.runs[0].text; - } else if ( - data && - data && - data.data && - data.data.title.simpleText - ) { - title = data.data.title.simpleText; + if (channel) { + // this thumbnail has channel information, can try channel blocklist + if (this.storage.blocklist.channels[channel] && !blockedElement.classList.contains('it-blocklisted-channel')) { + // blocked channel? = block all videos from that channel + blockedElement.classList.add('it-blocklisted-channel'); + } else if (!this.storage.blocklist.channels[channel] && blockedElement.classList.contains('it-blocklisted-channel')) { + // channel not blocked, show it + blockedElement.classList.remove('it-blocklisted-channel'); } + } - if (id && id[1]) { - ImprovedTube.messages.send({ - action: 'blocklist', - type: 'video', - id: id[1], - title: title - }); + if (node.querySelector("button.it-add-to-blocklist")) return; // skip blocklist button creation if one already exists - ImprovedTube.storage.blocklist.videos[id[1]] = { - title: title - }; + let button = document.createElement('button'), + svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg'), + path = document.createElementNS('http://www.w3.org/2000/svg', 'path'); - this.parentNode.parentNode.__dataHost.className += ' it-blocklisted-video'; + button.className = 'it-add-to-blocklist'; + button.addEventListener('click', function (event) { + if (this.parentNode.href) { + + const video = node.href.match(ImprovedTube.regex.video_id)?.[1], + channel = node.parentNode.__dataHost?.__data?.data?.shortBylineText?.runs?.[0]?.navigationEndpoint?.commandMetadata?.webCommandMetadata?.url ? node.parentNode.__dataHost.__data.data.shortBylineText.runs[0].navigationEndpoint.commandMetadata.webCommandMetadata.url.match(ImprovedTube.regex.channel).groups.name : undefined, + data = this.parentNode.__dataHost.__data?.data?.title, + blockedElement = node.blockedElement; + let title, + added = false, + type = 'video'; + + if (!video || !blockedElement) return; // need both video ID and blockedElement, otherwise bail + + if (data?.runs?.[0]?.text) { + title = data.runs[0].text; + } else if (data?.simpleText) { + title = data.simpleText; + } + if (channel && blockedElement.classList.contains('it-blocklisted-channel')) { + // unblocking channel + type = 'channel'; + } else if (blockedElement.classList.contains('it-blocklisted-video')) { + // unblocking blocklisted video + } else { + // nothing blocked, clicking should block this video + added = true; + } + ImprovedTube.messages.send({action: 'blocklist', + added: added, + type: type, + id: type == 'channel' ? channel : video, + title: title}); event.preventDefault(); event.stopPropagation(); } - } - }, true); + }, true); - svg.setAttributeNS(null, 'viewBox', '0 0 24 24'); - path.setAttributeNS(null, 'd', 'M12 2a10 10 0 100 20 10 10 0 000-20zm0 18A8 8 0 015.69 7.1L16.9 18.31A7.9 7.9 0 0112 20zm6.31-3.1L7.1 5.69A8 8 0 0118.31 16.9z'); + svg.setAttributeNS(null, 'viewBox', '0 0 24 24'); + path.setAttributeNS(null, 'd', 'M12 2a10 10 0 100 20 10 10 0 000-20zm0 18A8 8 0 015.69 7.1L16.9 18.31A7.9 7.9 0 0112 20zm6.31-3.1L7.1 5.69A8 8 0 0118.31 16.9z'); - svg.appendChild(path); - button.appendChild(svg); + svg.appendChild(path); + button.appendChild(svg); - node.appendChild(button); + node.appendChild(button); + this.elements.blocklist_buttons.push(button); + } else if (type === 'channel') { + let button = node.parentNode.parentNode.querySelector("button.it-add-channel-to-blocklist"), + id = location.href.match(ImprovedTube.regex.channel).groups.name; - if (this.elements && this.elements.blocklist_buttons && Array.isArray(this.elements.blocklist_buttons)){ - this.elements.blocklist_buttons.push(button); - } - } else if (type === 'channel') { - if (node.nodeName === 'A') { - try { - var id = node.href.match(ImprovedTube.regex.channel).groups.name; - - if (this.storage.blocklist.channels[id]) { - var parent = node.parentNode//.__dataHost.__dataHost; - - if ( parent.__dataHost.$.dismissible - //parent.nodeName === 'YTD-GRID-VIDEO-RENDERER' || - //parent.nodeName === 'YTD-VIDEO-META-BLOCK' - ) { - parent.__dataHost.$.dismissible.classList.add('it-blocklisted-video'); // this affects the title and co. as well - // parent.__dataHost.$.ytd-compact-video-renderer.classList.add('it-blocklisted-video'); - } + // skip channel blocklist button creation if one already exists + if (button) { + if (this.storage.blocklist.channels[id] && button.added) { + button.innerText = 'Remove from blocklist'; + button.added = false; + } else if (!this.storage.blocklist.channels[id] && !button.added) { + button.innerText = 'Add to blocklist'; + button.added = true; } - } catch (err) {} - } else { - var button = this.elements.blocklistChannel || document.createElement('button'), - id = location.href.match(ImprovedTube.regex.channel).groups.name; + return; + } + button = document.createElement('button'); button.className = 'it-add-channel-to-blocklist'; if (this.storage.blocklist.channels[id]) { button.innerText = 'Remove from blocklist'; - button.added = true; + button.added = false; } else { button.innerText = 'Add to blocklist'; - button.added = false; + button.added = true; } button.addEventListener('click', function (event) { - var data = this.parentNode.__dataHost.__data.data, + const data = ytInitialData.metadata.channelMetadataRenderer, + //let data = this.parentNode.__dataHost.__data.data, id = location.href.match(ImprovedTube.regex.channel).groups.name; - this.added = !this.added; - - ImprovedTube.messages.send({ - action: 'blocklist', - type: 'channel', - id: id, - title: data.title, - prevent: data.avatar.thumbnails[0].url - }); - - ImprovedTube.storage.blocklist.channels[id] = { - title: data.title, - prevent: data.avatar.thumbnails[0].url - }; - - if (this.added) { + if (this.added) { // adding + ImprovedTube.storage.blocklist.channels[id] = {title: data.title, + preview: data.avatar.thumbnails[0].url}; button.innerText = 'Remove from blocklist'; - } else { + } else { // removing + delete ImprovedTube.storage.blocklist.channels[id]; button.innerText = 'Add to blocklist'; } + ImprovedTube.messages.send({action: 'blocklist', + added: this.added, + type: 'channel', + id: id, + title: data.title, + preview: data.avatar.thumbnails[0].url}); + this.added = !this.added; event.preventDefault(); event.stopPropagation(); - - return false; }, true); + node.parentNode.parentNode.appendChild(button); this.elements.blocklist_buttons.push(button); + } else if (arguments.length == 0) { + // scan whole page + for (let thumbnails of document.querySelectorAll('a.ytd-thumbnail[href]')) { + this.blocklist('video', thumbnails); + } + if (document.querySelector('YT-SUBSCRIBE-BUTTON-VIEW-MODEL')) { + this.blocklist('channel', document.querySelector('YT-SUBSCRIBE-BUTTON-VIEW-MODEL')); + } + } + } else { + // remove blocklist buttons + for (let blocked of this.elements.blocklist_buttons) { + blocked.remove(); + } + this.elements.blocklist_buttons = []; + // clear observers list + if (this.elements.observerList) { + this.elements.observerList = []; + // release observer + ImprovedTube.blocklistObserver.disconnect(); + } + // remove all blocks from videos\channels + for (let blocked of document.querySelectorAll('.it-blocklisted-video, .it-blocklisted-channel')) { + blocked.classList.remove('it-blocklisted-video'); + blocked.classList.remove('it-blocklisted-channel'); + } + } +}; - node.parentNode.parentNode.appendChild(button); +ImprovedTube.blocklistObserver = new MutationObserver(function (mutationList) { + for (var mutation of mutationList) { + const video = mutation.target.href.match(ImprovedTube.regex.video_id)?.[1], + channel = mutation.target.parentNode.__dataHost?.__data?.data?.shortBylineText?.runs?.[0]?.navigationEndpoint?.commandMetadata?.webCommandMetadata?.url ? mutation.target.parentNode.__dataHost.__data.data.shortBylineText.runs[0].navigationEndpoint.commandMetadata.webCommandMetadata.url.match(ImprovedTube.regex.channel).groups.name : undefined, + blockedElement = mutation.target.blockedElement; + + if (!video || !blockedElement) return; // need both video ID and blockedElement, otherwise bail + + if (ImprovedTube.storage.blocklist.videos[video]) { + if (!blockedElement.classList.contains('it-blocklisted-video')) { + blockedElement.classList.add('it-blocklisted-video'); + } + } else { + if (blockedElement.classList.contains('it-blocklisted-video')) { + blockedElement.classList.remove('it-blocklisted-video'); + } + } - this.elements.blocklistChannel = button; + + if (channel && ImprovedTube.storage.blocklist.channels[channel] && !blockedElement.classList.contains('it-blocklisted-channel')) { + // blocked channel? = block all videos from that channel + blockedElement.classList.add('it-blocklisted-channel'); + } else if ((!channel || !ImprovedTube.storage.blocklist.channels[channel]) && blockedElement.classList.contains('it-blocklisted-channel')) { + // channel not blocked, show it + blockedElement.classList.remove('it-blocklisted-channel'); } + } -}; +});