Tries to revert some changes to the youtube theater / fullscreen mode to be like the old UI
// ==UserScript==
// @name YouTube Theater Mode Fix
// @version 2.2
// @description Tries to revert some changes to the youtube theater / fullscreen mode to be like the old UI
// @author Torkelicious
// @icon https://www.youtube.com/favicon.ico
// @license GPL-3.0-or-later
// @match https://www.youtube.com/*
// @run-at document-start
// @namespace https://greasyfork.org/users/1403155
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_registerMenuCommand
// ==/UserScript==
(function () {
'use strict';
// avoid loading more than once !!!
if (window.ytTheaterFixLoaded) return;
window.ytTheaterFixLoaded = true;
const DEFAULTS = { mastheadBehavior: 'relative' };
const COSMETIC = [
'.ytp-fullscreen-grid-hover-overlay',
'.ytp-fullscreen-grid-hover-overlay-chevron',
'.ytp-fullscreen-grid-stills-container'
];
const STYLE_ID = 'yt-theater-fix-styles';
const STYLE_TEXT = `
ytd-app { overflow: auto !important; }
ytd-app[scrolling] {
position: absolute !important;
top: 0 !important; left: 0 !important;
right: calc((var(--ytd-app-fullerscreen-scrollbar-width) + 1px)*-1) !important;
bottom: 0 !important;
overflow-x: auto !important;
}
ytd-watch-flexy[full-bleed-player] #single-column-container.ytd-watch-flexy,
ytd-watch-flexy[full-bleed-player] #columns.ytd-watch-flexy {
display: flex !important;
}
/* Keep controls visible and hide the new fullscreen grid UI variants */
.ytp-fullscreen-grid-peeking.ytp-full-bleed-player:not(.ytp-autohide) .ytp-chrome-bottom {
bottom: 0 !important; opacity: 1 !important;
}
#movie_player:not(.ytp-grid-ended-state) .ytp-fullscreen-grid {
display: none !important; top: 100% !important; opacity: 0 !important;
}
${COSMETIC.map(sel => `${sel} { display: none !important; }`).join('\n')}
.html5-video-player.ytp-fullscreen:is(.ytp-fullscreen-grid-peeking,.ytp-fullscreen-grid-active) .ytp-fullscreen-grid {
display: none !important;
}
.html5-video-player.ytp-fullscreen:is(.ytp-fullscreen-grid-peeking,.ytp-fullscreen-grid-active) .ytp-gradient-bottom {
display: none !important;
}
/* Generic fallbacks for renamed classes */
.html5-video-player.ytp-fullscreen [class*="fullscreen-grid"] { display: none !important; }
.html5-video-player.ytp-fullscreen [class*="gradient-bottom"] { display: none !important; }
.html5-video-player.ytp-fullscreen:is(.ytp-fullscreen-grid-peeking,.ytp-fullscreen-grid-active) .ytp-chrome-bottom {
bottom: 0px !important;
}
.html5-video-player.ytp-fullscreen:is(.ytp-fullscreen-grid-peeking,.ytp-fullscreen-grid-active):not(:is(.ytp-autohide,.ytp-autohide-active)) .ytp-chrome-bottom {
opacity: unset !important;
}
.html5-video-player.ytp-fullscreen:is(.ytp-fullscreen-grid-peeking,.ytp-fullscreen-grid-active) .ytp-overlays-container {
bottom: calc(var(--yt-delhi-bottom-controls-height, 72px) + 30px) !important;
}
.html5-video-player.ytp-fullscreen:is(.ytp-fullscreen-grid-peeking,.ytp-fullscreen-grid-active):not(:is(.ytp-autohide,.ytp-autohide-active)) .ytp-overlays-container {
opacity: unset !important;
}
div.html5-video-player {
--ytp-grid-scroll-percentage: 0 !important;
}
div.html5-video-player.ytp-fullscreen-grid-active .ytp-chrome-bottom {
display: block !important;
}
`;
// defensive GM wrappers (in case manager doesn't expose GM_* exactly)
const hasGMGet = typeof GM_getValue === 'function';
const hasGMSet = typeof GM_setValue === 'function';
const gmGet = (k) => (hasGMGet ? GM_getValue(k) : undefined) ?? DEFAULTS[k];
const gmSet = (k, v) => { if (hasGMSet) GM_setValue(k, v); };
const setImp = (el, prop, val) => el?.style?.setProperty(prop, val, 'important');
const removeImp = (el, prop) => el?.style?.removeProperty(prop);
function injectStylesEarly() {
if (document.getElementById(STYLE_ID)) return;
const st = document.createElement('style');
st.id = STYLE_ID;
st.textContent = STYLE_TEXT;
(document.head || document.documentElement).appendChild(st);
}
function applyWatchFixes() {
const watch = document.querySelector('ytd-watch-flexy');
const masthead = document.querySelector('#masthead-container');
const app = document.querySelector('ytd-app');
const pm = document.getElementById('page-manager');
if (!watch || !app) return;
const player = document.getElementById('movie_player') || document.querySelector('.html5-video-player');
const behavior = gmGet('mastheadBehavior');
// mode detection
const isTheater = watch.hasAttribute('theater');
const isFullscreen =
watch.hasAttribute('fullscreen') ||
!!document.fullscreenElement ||
player?.classList.contains('ytp-fullscreen');
const hasMini = document.querySelector('ytd-miniplayer')?.hasAttribute('active');
if (isTheater || isFullscreen) {
if (!hasMini && masthead) {
if (isFullscreen || behavior === 'hide') {
setImp(masthead, 'display', 'none');
} else if (behavior === 'relative') {
removeImp(masthead, 'display');
setImp(masthead, 'position', 'relative');
setImp(masthead, 'z-index', '2020');
} else {
removeImp(masthead, 'display');
removeImp(masthead, 'position');
removeImp(masthead, 'z-index');
}
}
if (!hasMini) {
setImp(app, 'overflow', 'auto');
if (app.hasAttribute('scrolling')) {
setImp(app, 'position', 'absolute');
setImp(app, 'top', '0');
setImp(app, 'left', '0');
setImp(app, 'right', 'calc((var(--ytd-app-fullerscreen-scrollbar-width) + 1px)*-1)');
setImp(app, 'bottom', '0');
setImp(app, 'overflow-x', 'auto');
}
}
const sc =
document.querySelector('#single-column-container.ytd-watch-flexy') ||
document.getElementById('single-column-container');
const cols =
document.querySelector('#columns.ytd-watch-flexy') ||
document.getElementById('columns');
if (sc) setImp(sc, 'display', 'flex');
if (cols) setImp(cols, 'display', 'flex');
if (behavior === 'relative' && !isFullscreen && pm) setImp(pm, 'margin-top', '0');
} else {
if (masthead) {
removeImp(masthead, 'display');
removeImp(masthead, 'position');
removeImp(masthead, 'z-index');
}
if (pm) removeImp(pm, 'margin-top');
}
}
let debounceTimer = null;
function scheduleRun(delay = 100) {
clearTimeout(debounceTimer);
debounceTimer = setTimeout(() => {
applyWatchFixes();
// Retry once if watch page not loaded yet
if (!document.querySelector('ytd-watch-flexy') && location.pathname.includes('/watch')) {
setTimeout(applyWatchFixes, 500);
}
}, delay);
}
const observer = new MutationObserver((mutations) => {
for (const m of mutations) {
if (
(m.type === 'childList' && [...m.addedNodes].some(n => n.matches?.('ytd-watch-flexy, ytd-miniplayer, #movie_player, .html5-video-player'))) ||
(m.type === 'attributes' && (
m.target.matches?.('ytd-watch-flexy, ytd-miniplayer') ||
m.target.id === 'movie_player' ||
m.target.matches?.('.html5-video-player')
))
) {
scheduleRun(50);
break;
}
}
});
function startObserver() {
const target = document.querySelector('ytd-app') || document.documentElement;
observer.observe(target, {
childList: true,
subtree: true,
attributes: true,
attributeFilter: ['theater', 'fullscreen', 'active', 'class']
});
}
// settings dialog using DOM methods to avoid TrustedTypes TrustedHTML errors
function showSettings() {
if (document.getElementById('yt-theater-fix-settings')) return;
const current = gmGet('mastheadBehavior');
const overlay = document.createElement('div');
overlay.id = 'yt-theater-fix-settings';
overlay.style.cssText = 'position:fixed;inset:0;display:flex;align-items:center;justify-content:center;z-index:99999;background-color:rgba(0,0,0,0.6)';
const dialog = document.createElement('div');
dialog.style.cssText = 'background:#222;color:#fff;padding:18px;border-radius:8px;min-width:320px;font-family:Arial,Helvetica,sans-serif;box-shadow:0 4px 12px rgba(0,0,0,0.5);';
const title = document.createElement('h3');
title.textContent = 'Theater Mode Settings';
title.style.cssText = 'margin:0 0 12px 0;font-size:16px';
const options = document.createElement('div');
options.style.cssText = 'display:flex;flex-direction:column;gap:8px';
function mkOption(val, text) {
const label = document.createElement('label');
const input = document.createElement('input');
input.type = 'radio';
input.name = 'mf';
input.value = val;
if (current === val) input.checked = true;
label.appendChild(input);
label.appendChild(document.createTextNode(' ' + text));
return label;
}
options.appendChild(mkOption('relative', 'Show masthead (scrollable)'));
options.appendChild(mkOption('hide', 'Hide masthead'));
options.appendChild(mkOption('fixed', 'Show masthead (fixed)'));
const controls = document.createElement('div');
controls.style.cssText = 'display:flex;gap:8px;justify-content:flex-end;margin-top:12px';
const btnCancel = document.createElement('button');
btnCancel.id = 'yt-m-cancel';
btnCancel.textContent = 'Cancel';
const btnSave = document.createElement('button');
btnSave.id = 'yt-m-save';
btnSave.textContent = 'Save & Reload';
controls.appendChild(btnCancel);
controls.appendChild(btnSave);
dialog.appendChild(title);
dialog.appendChild(options);
dialog.appendChild(controls);
overlay.appendChild(dialog);
(document.documentElement || document.body || document).appendChild(overlay);
const close = () => overlay.remove();
overlay.addEventListener('click', (e) => { if (e.target === overlay) close(); });
btnCancel.onclick = close;
btnSave.onclick = () => {
const v = document.querySelector('input[name="mf"]:checked')?.value || DEFAULTS.mastheadBehavior;
gmSet('mastheadBehavior', v);
close();
location.reload();
};
}
// register menu command fail silently
try {
if (typeof GM_registerMenuCommand === 'function') GM_registerMenuCommand('Theater Mode Settings', showSettings);
} catch (e) { /* ignore */ }
// Re run on SPA navigations and fullscreen toggles
window.addEventListener('yt-navigate-finish', () => scheduleRun(50), { passive: true });
document.addEventListener('fullscreenchange', () => scheduleRun(20), { passive: true });
// Init
injectStylesEarly();
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', () => {
scheduleRun(50);
startObserver();
});
} else {
scheduleRun(50);
startObserver();
}
})();