YT Feed Sorter

Sorts the YouTube feed so that all scheduled streams come before archived videos.

当前为 2022-12-14 提交的版本,查看 最新版本

// ==UserScript==
// @name         YT Feed Sorter
// @namespace    YTFeedSorter
// @version      0.5
// @description  Sorts the YouTube feed so that all scheduled streams come before archived videos.
// @match        *://*.youtube.com/*
// @author       KFP
// ==/UserScript==

(function() {
    'use strict';

    let feedSorted = false;
    const feedSelector = 'ytd-browse[page-subtype="subscriptions"][role="main"] #contents.ytd-section-list-renderer';
    const blockSelector = '#items.ytd-grid-renderer';
    const liveSelector = '#video-badges:not([hidden])';
    const soonSelector = 'ytd-toggle-button-renderer';
    const sortedClass = 'ytfeedsorter-sorted';

    const sortBlock = block => {
        const wasSorted = block.classList.contains(sortedClass);
        if (!wasSorted) block.classList.add(sortedClass);
        setTimeout(() => {
            [...block.children].sort((a, b) => {
                const ai = a.root.querySelector(liveSelector) ? 2 : a.root.querySelector(soonSelector) ? 1 : 0;
                const bi = b.root.querySelector(liveSelector) ? 2 : b.root.querySelector(soonSelector) ? 1 : 0;
                return (ai > bi) ? -1 : (ai < bi) ? 1 : 0;
            }).forEach(item => block.appendChild(item));
        }, wasSorted ? 200 : 0);
    };

    const observer = new MutationObserver(mutations => {
        for (const mut of mutations) {
            for (const added of mut.addedNodes) {
                document.querySelectorAll(blockSelector).forEach(sortBlock);
            }
        }
    });

    setInterval(() => {
        const feed = document.querySelector(feedSelector);
        if (feed) {
            if (feedSorted) return;
            document.querySelectorAll(blockSelector).forEach(sortBlock);
            observer.observe(feed, {childList: true});
            feedSorted = true;
        } else if (feedSorted) {
            observer.disconnect();
            feedSorted = false;
        }
    }, 100);
})();