YouTube - Force Compact Grid (increases max # videos per row)

Force YouTube to show compact grid (max 6 videos per row) rather than "slim" grid (max 3 videos per row)

目前为 2023-02-03 提交的版本,查看 最新版本

// ==UserScript==
// @name         YouTube - Force Compact Grid (increases max # videos per row)
// @namespace    https://gist.github.com/lbmaian/8c6961584c0aebf41ee7496609f60bc3
// @version      0.1
// @description  Force YouTube to show compact grid (max 6 videos per row) rather than "slim" grid (max 3 videos per row)
// @author       lbmaian
// @match        https://www.youtube.com/*
// @exclude      https://www.youtube.com/embed/*
// @icon         https://www.youtube.com/favicon.ico
// @run-at       document-start
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    const DEBUG = false;

    const logContext = '[YouTube - Force Compact Grid]';

    var debug;
    if (DEBUG) {
        debug = function(...args) {
            console.debug(logContext, ...args);
        };
    } else {
        debug = function() {};
    }

    function log(...args) {
        console.log(logContext, ...args);
    }

    function info(...args) {
        console.info(logContext, ...args);
    }

    function warn(...args) {
        console.warn(logContext, ...args);
    }

    function error(...args) {
        console.error(logContext, ...args);
    }

    function updateResponseData(response, label) {
        const tabs = response?.contents?.twoColumnBrowseResultsRenderer?.tabs;
        debug(label, 'contents.twoColumnBrowseResultsRenderer.tabs', tabs);
        if (tabs) {
            for (const tab of tabs) {
                const tabRenderer = tab.tabRenderer;
                if (tabRenderer) {
                    const richGridRenderer = tabRenderer.content?.richGridRenderer;
                    if (richGridRenderer && richGridRenderer.style == 'RICH_GRID_STYLE_SLIM') {
                        log(label, 'tab', tabRenderer.title, 'tabRenderer.content.richGridRenderer.style:', richGridRenderer.style, '=> RICH_GRID_STYLE_COMPACT');
                        richGridRenderer.style = 'RICH_GRID_STYLE_COMPACT';
                    }
                }
            }
        }
    }

    // Note: Both of the following event listeners are too late:
    // ytd-app's own yt-page-data-fetched event listener (onYtPageDataFetched) already fires
    // by the time our own yt-page-data-fetched event listener fires,
    // and yt-page-data-fetched fires before yt-navigate-finish fires

    // document.addEventListener('yt-page-data-fetched', evt => {
    //     debug('Navigated to', evt.detail.pageData.url);
    //     debug(evt);
    //     updateResponseData(evt.detail.pageData.response, 'yt-page-data-fetched pageData.response');
    // });

    // document.addEventListener('yt-navigate-finish', evt => {
    //     debug('Navigated to', evt.detail.response.url);
    //     debug(evt);
    //     updateResponseData(evt.detail.response.response, 'yt-navigate-finish response.response');
    // });

    document.addEventListener('DOMContentLoaded', evt => {
        // Handle the initial page
        debug('ytInitialData', window.ytInitialData);
        updateResponseData(window.ytInitialData, 'ytInitialData');

        // Handle changing tabs (e.g. 'videos' or 'live' tab)
        // Need to hook into ytd-app's ytd-app's own yt-page-data-fetched event listener (onYtPageDataFetched),
        // so that we can modify the data before that event listener fires
        const ytdApp = document.getElementsByTagName('ytd-app')[0];
        debug('ytd-app', ytdApp);
        if (!ytdApp) {
            error('unexpectedly could not find ytd-app after page load');
            return;
        }
        const origOnYtPageDataFetched = ytdApp.onYtPageDataFetched;
        ytdApp.onYtPageDataFetched = function(evt, detail) {
            debug('Navigated to', detail.pageData.url);
            debug(evt);
            updateResponseData(evt.detail.pageData.response, 'yt-page-data-fetched pageData.response');
            return origOnYtPageDataFetched.call(this, evt, detail);
        };
    });
})();