Hover a thumbnail to see icons at the right: "Not interested" and "Don't recommend channel"
目前為
// ==UserScript==
// @name YT: not interested in one click
// @description Hover a thumbnail to see icons at the right: "Not interested" and "Don't recommend channel"
// @version 1.0.1
// @match https://www.youtube.com/*
// @noframes
// @grant none
// @author wOxxOm
// @namespace wOxxOm.scripts
// @license MIT License
// ==/UserScript==
const ME = 'yt-one-click-dismiss';
const THUMB_TAG = 'ytd-thumbnail';
const TYPE_VIDEO = 'NOT_INTERESTED';
const TYPE_CHANNEL = 'REMOVE';
const ELEMENTS = Object.create(null);
let STYLE;
const isThumb = el => el.localName === THUMB_TAG;
addEventListener('mouseover', onHover);
addEventListener('click', onClick);
function onHover(e) {
const thumb = e.composedPath().find(isThumb);
if (thumb && !thumb.getElementsByClassName(ME)[0]) {
if (!STYLE) init(thumb);
for (const type in getMenuItems(thumb))
if (ELEMENTS[type])
thumb.appendChild(ELEMENTS[type]);
}
}
async function onClick({target}) {
const {block} = target.classList.contains(ME) && target.dataset;
if (!block) return;
const index = STYLE.sheet.insertRule('ytd-menu-popup-renderer { display: none !important }');
const entry = target.closest('ytd-rich-item-renderer, ytd-compact-video-renderer');
const more = entry.querySelector('yt-icon-button.dropdown-trigger');
await 0;
more.dispatchEvent(new Event('tap'));
await 0;
for (const el of document.querySelector('ytd-menu-popup-renderer [role="listbox"]').children) {
if (block === 'video' && el.data.icon.iconType === 'NOT_INTERESTED' ||
block === 'channel' && el.data.icon.iconType === 'REMOVE') {
el.click();
await new Promise(setTimeout);
break;
}
}
document.body.click()
STYLE.sheet.deleteRule(index);
}
function getMenuItems(thumb) {
const items = {};
try {
for (const {menuServiceItemRenderer: {icon, text}} of thumb.data.menu.menuRenderer.items)
items[icon.iconType] = text.runs[0].text;
} catch (e) {}
return items;
}
function init(thumb) {
const menuItems = getMenuItems(thumb);
for (const [type, iconType, title] of [
['video', TYPE_VIDEO, 'Not interested!'],
['channel', TYPE_CHANNEL, "Don't recommend channel!"],
]) {
const el = document.createElement('div');
el.className = ME;
el.dataset.block = type;
el.title = menuItems[iconType] || title;
ELEMENTS[iconType] = el;
}
STYLE = document.createElement('style');
STYLE.textContent = /*language=CSS*/ `
${THUMB_TAG}:hover .${ME} {
display: block;
}
.${ME} {
display: none;
position: absolute;
width: 16px;
height: 16px;
border-radius: 100%;
border: 2px solid #fff;
right: 8px;
background: #0006;
box-shadow: .5px .5px 7px #000;
cursor: pointer;
opacity: .75;
z-index: 100;
}
.${ME}:hover {
opacity: 1;
}
.${ME}:active {
color: yellow;
}
.${ME}[data-block="video"] {
top: 70px;
}
.${ME}[data-block="channel"] {
top: 100px;
}
.${ME}::after {
content: "";
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
height: 0;
margin: auto;
border: none;
border-bottom: 2px solid #fff;
}
.${ME}[data-block="video"]::after {
transform: rotate(45deg);
}
.${ME}[data-block="channel"]::after {
margin: auto 3px;
}
`.replace(/;/g, '!important;');
document.head.appendChild(STYLE);
}