Better YouTube Theater Mode

Make YouTube's theater mode work like Twitch's one

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name              Better YouTube Theater Mode
// @namespace         https://github.com/NightFeather0615
// @version           1.3.7
// @description       Make YouTube's theater mode work like Twitch's one
// @author            NightFeather
// @match             *://www.youtube.com/*
// @icon              https://www.google.com/s2/favicons?sz=64&domain=youtube.com
// @grant             none
// @license           MPL-2.0
// ==/UserScript==

/* jshint esversion: 8 */
/* jshint -W083 */
/* jshint multistr: true */

/* eslint no-multi-str: 0 */

const waitElement = async (selector) => {
    'use strict';

    while (document.querySelector(selector) === null) {
        await new Promise((resolve, reject) => requestAnimationFrame(resolve));
    }

    return document.querySelector(selector);
};

const asyncSleep = async (ms) => {
    'use strict';

    return new Promise(resolve => setTimeout(resolve, ms));
};

(async function() {
    'use strict';

    let isPlayerSetup = false;

    const trySetupPlayer = async () => {
        let isUrlVaild = window.location.pathname.startsWith("/watch") || window.location.pathname.startsWith("/live");

        if (!isUrlVaild || isPlayerSetup) return;

        isPlayerSetup = true;

        let theaterBtn = await waitElement(".ytp-size-button.ytp-button");

        let mashheadContainer = await waitElement("#masthead-container");
        let pageManager = await waitElement("ytd-page-manager");

        let videoBleedContainer = await waitElement("#full-bleed-container");
        let lastPlayerHeight = -1;

        let moviePlayer = await waitElement("#movie_player");

        console.log(`[YT Better Theater Mode] Video player initialized`);

        const processTheaterMode = async () => {
            await asyncSleep(50);

            let isTheaterView = document.querySelector("#masthead").theater;
            let isFullscreen = moviePlayer.classList.contains("ytp-fullscreen");
            let liveChat = document.querySelector("ytd-live-chat-frame");

            if (isTheaterView && videoBleedContainer.clientHeight > 0 && isUrlVaild) {
                if (videoBleedContainer.clientHeight === lastPlayerHeight) return;

                console.log(`[YT Better Theater Mode] Applying styles`);

                mashheadContainer.hidden = true;

                videoBleedContainer.style.maxHeight = "100vh";
                videoBleedContainer.style.height = "100vh";

                moviePlayer.classList.remove("ytp-hide-info-bar");

                pageManager.style.marginTop = "0px";

                if (liveChat) {
                    liveChat.style.top = "0px";
                    liveChat.style.borderRadius = "0 0 0 0";
                }
            } else {
                if (videoBleedContainer.clientHeight === 0) return;

                console.log(`[YT Better Theater Mode] Resetting styles`);

                mashheadContainer.hidden = false;

                videoBleedContainer.style.maxHeight = "";
                videoBleedContainer.style.height = "";

                if (!isFullscreen) {
                    moviePlayer.classList.add("ytp-hide-info-bar");
                }

                pageManager.style.marginTop = "var(--ytd-masthead-height,var(--ytd-toolbar-height))";

                if (liveChat) {
                    liveChat.style.borderRadius = "12px";
                }
            }

            console.log(`[YT Better Theater Mode] Triggering resize event`);
            let resizeEvent = window.document.createEvent("UIEvents");
            resizeEvent.initUIEvent("resize", true, false, window, 0);
            window.dispatchEvent(resizeEvent);

            lastPlayerHeight = videoBleedContainer.clientHeight;
        }

        console.log(`[YT Better Theater Mode] Setting up theater mode`);

        await processTheaterMode();

        let videoBleedContainerObserver = new ResizeObserver(processTheaterMode);
        videoBleedContainerObserver.observe(videoBleedContainer);

        theaterBtn.onclick = processTheaterMode;
    }

    await trySetupPlayer();
    document.addEventListener("selectionchange", trySetupPlayer);
})();