Greasy Fork is available in English.
此脚本将 YouTube 播放器调整为延伸至屏幕底部,提供类似 Twitch.tv 的沉浸式观看体验,减少干扰。
当前为
// ==UserScript==
// @name Better YouTube Theater Mode
// @name:zh-TW 更佳的 YouTube 劇場模式
// @name:zh-CN 更佳的 YouTube 剧场模式
// @name:ja 改良されたYouTubeシアターモード
// @icon https://www.youtube.com/img/favicon_48.png
// @author ElectroKnight22
// @namespace electroknight22_youtube_better_theater_mode_namespace
// @version 1.3.1
// @match *://www.youtube.com/*
// @match *://www.youtube-nocookie.com/*
// @grant GM_addStyle
// @grant GM.addStyle
// @license MIT
// @description This script adjusts YouTube's player to extend to the bottom of the screen, creating a Twitch.tv-like viewing experience with fewer distractions.
// @description:zh-TW 此腳本會將 YouTube 播放器調整為延伸至螢幕底部,提供類似 Twitch.tv 的沉浸式觀看體驗,減少干擾。
// @description:zh-CN 此脚本将 YouTube 播放器调整为延伸至屏幕底部,提供类似 Twitch.tv 的沉浸式观看体验,减少干扰。
// @description:ja このスクリプトは、YouTubeのプレーヤーを画面の下部まで拡張し、Twitch.tvのようなより没入感のある視聴体験を提供します。
// ==/UserScript==
/*jshint esversion: 11 */
(function () {
'use strict';
const GMCustomAddStyle = typeof GM_info !== 'undefined' ? GM_addStyle : GM.addStyle;
let mastHeadContainer = null;
let pageManager = null;
let chatFrame = null;
let isTheaterMode = false;
let chatCollapsed = true;
let resizeTimeout = null;
const RETRY_COUNT = 5;
const RETRY_DELAY = 500;
const retryOperation = (operation, retries, delay) => {
return new Promise((resolve, reject) => {
const attempt = () => {
const result = operation();
if (result) {
resolve(result);
} else if (retries > 0) {
setTimeout(() => attempt(retries - 1), delay);
} else {
reject(new Error('Operation failed after retries'));
}
};
attempt();
});
};
function updateFullscreenStatus() {
isPlayerFullscreen = pageManager?.getState()?.watch?.isWatchFullscreen || false;
}
function updateStyle() {
if (!mastHeadContainer) {
mastHeadContainer = document.querySelector('#masthead-container');
}
if (mastHeadContainer) {
const chatWidth = chatFrame?.offsetWidth || 0;
mastHeadContainer.style.maxWidth = (chatFrame && isTheaterMode && !chatCollapsed && chatFrame.getBoundingClientRect().top === 0)
? `calc(100% - ${chatWidth}px)`
: '100%';
}
}
function findElement(selector, retries = RETRY_COUNT, delay = RETRY_DELAY) {
return retryOperation(() => document.querySelector(selector), retries, delay)
.catch(() => console.warn(`Element not found: ${selector}`));
}
function forceUpdateAll() {
isTheaterMode = pageManager.getState().watch.isTheaterMode;
chatCollapsed = pageManager.getState().watch.chatCollapsed;
updateStyle();
}
async function prepNewPage() {
pageManager = await findElement('.ytd-page-manager');
chatFrame = await findElement('ytd-live-chat-frame');
forceUpdateAll();
}
function theaterToggled(event) {
isTheaterMode = !!event?.detail?.enabled;
}
function chatToggled(event) {
chatCollapsed = !!event?.detail;
}
function attachEventListeners() {
window.addEventListener('yt-set-theater-mode-enabled', (event) => {
theaterToggled(event);
}, true);
window.addEventListener('yt-chat-collapsed-changed', (event) => {
chatToggled(event);
}, true);
window.addEventListener('yt-navigate-finish', prepNewPage, true);
window.addEventListener('player-api-ready', updateStyle, true);
}
function applyStaticStyles() {
GMCustomAddStyle(`
ytd-watch-flexy[full-bleed-player] #full-bleed-container.ytd-watch-flexy {
max-height: calc(100vh - var(--ytd-watch-flexy-masthead-height)) !important;
}
ytd-live-chat-frame[theater-watch-while][rounded-container],
#panel-pages.yt-live-chat-renderer {
border-radius: 0 !important;
border-top: 0px !important;
border-bottom: 0px !important;
}
ytd-watch-flexy[fixed-panels] #chat.ytd-watch-flexy {
top: 0 !important;
}
`);
}
function init() {
applyStaticStyles();
attachEventListeners();
prepNewPage();
}
init();
})();