Youtube favorites channels

Highlights videos of the channels that you mark as favorite (only for Grid view). Tap the heart icon on the channel page to add it to your favorites.

您需要先安装一个扩展,例如 篡改猴Greasemonkey暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴暴力猴,之后才能安装此脚本。

您需要先安装一个扩展,例如 篡改猴Userscripts ,之后才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。

您需要先安装用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Youtube favorites channels
// @name:ru      Избранные каналы Youtube
// @namespace    http://tampermonkey.net/
// @version      0.2
// @description  Highlights videos of the channels that you mark as favorite (only for Grid view). Tap the heart icon on the channel page to add it to your favorites.
// @description:ru  Выделяет видео избранных каналов среди остальных (только в режиме Сетки). Нажмите значок сердца на странице канала, чтобы добавить его в избранное.
// @author       dark1103
// @include      https://www.youtube.com/*
// @icon         https://www.google.com/s2/favicons?domain=youtube.com
// @require      http://code.jquery.com/jquery-3.4.1.min.js
// @grant        GM_getValue
// @grant        GM_setValue
// ==/UserScript==

(function() {
    'use strict';
    var bg_color = 'lightgoldenrodyellow';



    function getFav(){
         var fav = GM_getValue("fav1");
        if(fav === undefined){
            fav = [];
        }
        return fav;
    }

    function onLoaded(){
        var name = $('#channel-name #text').eq(0).text();
        var isFav = getFav().includes(name);
        $('#fav-button').remove();
        var node = $('<div id="fav-button" class="style-scope ytd-c4-tabbed-header-renderer" style="line-height: 38px;font-size: large;cursor: pointer;">' + (isFav ? '💖' : '🤍') + '</div>');
        node.appendTo($('#inner-header-container #buttons'));

        node.on('click', function(){

            var fav = getFav();

            if(isFav){
                fav = fav.filter(item => item !== name);
                isFav = false;
            }else{
                fav.push(name);
                isFav = true;
            }

            $('#fav-button').html(isFav ? '💖' : '🤍');
            GM_setValue("fav1", fav);
        });

    }
    function highlightFav(){
        if(location.href === 'https://www.youtube.com/feed/subscriptions'){
            var fav = getFav();
            $('ytd-grid-video-renderer').filter(function(){
                var name = $(this).find('#channel-name #text').text();
                return fav.includes(name);
            }).css('background-color', bg_color);
        }
    }

    function createMutationListener(){
        var target = document.querySelector('body')

        // Create an observer instance linked to the callback function
        const observer2 = new MutationObserver(function(mutationsList, observer) {
            // Use traditional 'for loops' for IE 11
            for(const mutation of mutationsList) {
                if (mutation.type === 'childList') {
                    var target = $(mutation.target);
                    //console.log(target);
                    if(target.prop("tagName") === 'ytd-thumbnail-overlay-time-status-renderer'.toUpperCase()){
                        highlightFav();
                    }
                }
            }
        });

        // Start observing the target node for configured mutations
        observer2.observe(target, { attributes: true, childList: true, subtree: true });
    }

    $(document).ready(function(){
        onLoaded();
        highlightFav();
        createMutationListener();
    });


    var oldHref = document.location.href;
    var bodyList = document.querySelector("body")
        ,observer = new MutationObserver(function(mutations) {

            mutations.forEach(function(mutation) {

                if (oldHref != document.location.href) {
                    oldHref = document.location.href;
                    setTimeout(function(){
                        onLoaded();
                        highlightFav();
                    }, 1000);
                    onLoaded();
                    highlightFav();
                }

            });

        });

    observer.observe(bodyList, {
        childList: true,
        subtree: true
    });

})();