YouTube Watch Later Remove Button on Hover

Show a remove button on hover over video thumbnails in the Watch Later list

θα χρειαστεί να εγκαταστήσετε μια επέκταση όπως το Tampermonkey, το Greasemonkey ή το Violentmonkey για να εγκαταστήσετε αυτόν τον κώδικα.

You will need to install an extension such as Tampermonkey to install this script.

θα χρειαστεί να εγκαταστήσετε μια επέκταση όπως το Tampermonkey ή το Violentmonkey για να εγκαταστήσετε αυτόν τον κώδικα.

θα χρειαστεί να εγκαταστήσετε μια επέκταση όπως το Tampermonkey ή το Userscripts για να εγκαταστήσετε αυτόν τον κώδικα.

You will need to install an extension such as Tampermonkey to install this script.

Θα χρειαστεί να εγκαταστήσετε μια επέκταση διαχείρισης κώδικα χρήστη για να εγκαταστήσετε αυτόν τον κώδικα.

(Έχω ήδη έναν διαχειριστή κώδικα χρήστη, επιτρέψτε μου να τον εγκαταστήσω!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(Έχω ήδη έναν διαχειριστή στυλ χρήστη, επιτρέψτε μου να τον εγκαταστήσω!)

// ==UserScript==
// @name         YouTube Watch Later Remove Button on Hover
// @namespace    http://tampermonkey.net/
// @version      0.6.2
// @description  Show a remove button on hover over video thumbnails in the Watch Later list
// @license MIT
// @match        https://www.youtube.com/*
// @run-at              document-start
// @grant               none
// @inject-into         page
// ==/UserScript==

(function () {
    'use strict';

    let scriptEnable = false;

    const insp = o => o ? (o.polymerController || o.inst || o || 0) : (o || 0);

    function getItemData(menu) {
        if (!menu) return;
        let items = ((menu || 0).menuRenderer || 0).items || 0;
        if (!(items.length >= 1)) return;
        const filtered = items.filter((entry) => {
            if (!entry || typeof entry !== 'object') return false;
            try {
                const t = (JSON.stringify(entry) || '');
                return t.includes('ACTION_REMOVE_VIDEO');
            } catch (e) {
                return false;
            }
        });
        if (filtered.length !== 1) return;
        let itemData = filtered[0];
        itemData = Object.values(itemData).filter(e => e.serviceEndpoint || e.command)[0];
        if (!itemData) return;
        return itemData;
    }

    const removeButtonOnclick = function (e) {
        const button = this;
        if (!scriptEnable) return;

        let videoElement = button.closest('ytd-thumbnail');
        if (!videoElement) return;
        let renderer = videoElement.closest('ytd-playlist-video-renderer.style-scope.ytd-playlist-video-list-renderer');
        if (!renderer) return;

        let data = insp(renderer).data || 0;
        const itemData = getItemData(data.menu);
        if (!itemData) return;

        e.preventDefault(); // Prevent the default action of the event
        e.stopPropagation(); // Stop the event from bubbling up
        e.stopImmediatePropagation(); // Prevents other listeners of the same event from being called

        const cntNode = (document.querySelector('ytd-app') || renderer);

        (function (data) {

            const a = data.serviceEndpoint;
            const b = data.command;

            a && this.ytComponentBehavior.resolveCommand(a);
            b && this.ytComponentBehavior.resolveCommand(b);

        }).call(insp(cntNode), itemData);

    };

    function createRemoveButton(videoElement) {
        let removeButton = document.createElement('button');
        removeButton.className = 'watch-later-remove-button';
        removeButton.textContent = 'Remove';
        removeButton.style.position = 'absolute';
        removeButton.style.top = '5px';
        removeButton.style.right = '5px';
        removeButton.style.zIndex = '1000';

        removeButton.onclick = removeButtonOnclick;
        videoElement.appendChild(removeButton);
    }

    const mouseenterHandler = function (e) {
        if (!e || !(e.target instanceof HTMLElement)) return;
        if (!scriptEnable) return;
        if (!e.target.classList.contains('ytd-playlist-video-renderer')) return;
        let videoElement = e.target.closest('ytd-thumbnail');
        if (!videoElement) return;
        let renderer = videoElement.closest('ytd-playlist-video-renderer.style-scope.ytd-playlist-video-list-renderer');
        if (!renderer || renderer.is !== 'ytd-playlist-video-renderer') return;
        let data = insp(renderer).data || 0;
        let itemData = getItemData(data.menu);
        if (!itemData) return;
        let button = videoElement.querySelector('button.watch-later-remove-button')
        if (!button) {
            createRemoveButton(videoElement);
        } else {
            button.style.display = '';
        }
    };

    const mouseleaveHandler = function (e) {
        if (!e || !(e.target instanceof HTMLElement)) return;
        if (!e.target.classList.contains('ytd-playlist-video-renderer')) return;
        let button = e.target.querySelector('button.watch-later-remove-button');
        if (button) {
            button.style.display = 'none';
        }
    };


    document.addEventListener('yt-navigate-finish', () => {

        const newEnable = location.pathname === '/playlist' && location.search.includes('list=WL');

        if (scriptEnable ^ newEnable) {

            if (scriptEnable) {
                scriptEnable = false;
                document.removeEventListener('mouseenter', mouseenterHandler, true);
                document.removeEventListener('mouseleave', mouseleaveHandler, true);
            } else if (newEnable) {
                scriptEnable = true;
                document.addEventListener('mouseenter', mouseenterHandler, true);
                document.addEventListener('mouseleave', mouseleaveHandler, true);
            }

        }

    }, false);

})();