Hide YouTube comments until at least 50% of the video has been watched (without skipping), to improve focus. Also blocks other distractions like recommendations.
// ==UserScript==
// @name YouTube Comments Unlock After Watch
// @namespace http://tampermonkey.net/
// @version 0.1
// @description Hide YouTube comments until at least 50% of the video has been watched (without skipping), to improve focus. Also blocks other distractions like recommendations.
// @author Adapted from Markus Dietl's script
// @match https://www.youtube.com/*
// @grant none
// @license MIT
// ==/UserScript==
(function() {
'use strict';
let video = null;
let watchedTime = 0;
let prevTime = 0;
let duration = 0;
let unlocked = false;
// Function to hide elements by class name
function hideElementsByClass(className) {
const elements = document.getElementsByClassName(className);
for (let i = 0; i < elements.length; i++) {
elements[i].style.display = 'none';
}
}
// Function to hide an element by ID
function hideElementById(id) {
const element = document.getElementById(id);
if (element) {
element.style.display = 'none';
}
}
// Function to show an element by ID
function showElementById(id) {
const element = document.getElementById(id);
if (element) {
element.style.display = '';
}
}
// Setup video event listeners
function setupVideo(v) {
video = v;
video.addEventListener('loadedmetadata', handleLoadedMetadata);
video.addEventListener('timeupdate', handleTimeUpdate);
video.addEventListener('seeked', handleSeeked);
// If metadata already loaded
if (video.duration && !isNaN(video.duration) && video.duration > 0) {
handleLoadedMetadata();
}
}
function handleLoadedMetadata() {
duration = video.duration;
watchedTime = 0;
prevTime = 0;
unlocked = false;
hideElementById('comments');
}
function handleTimeUpdate() {
if (unlocked || video.paused || isNaN(duration) || duration <= 0) return;
const delta = video.currentTime - prevTime;
if (delta > 0 && delta < 2) {
watchedTime += delta;
}
prevTime = video.currentTime;
if (watchedTime >= 0.5 * duration) {
unlocked = true;
showElementById('comments');
}
}
function handleSeeked() {
prevTime = video.currentTime;
}
// Create a mutation observer to monitor the DOM for changes
const observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
if (mutation.addedNodes && mutation.addedNodes.length > 0) {
// Always hide recommendations
hideElementsByClass('ytd-watch-next-secondary-results-renderer');
// Hide comments if not unlocked
if (!unlocked) {
hideElementById('comments');
}
// Check for added video element
mutation.addedNodes.forEach(function(node) {
if (node.tagName === 'VIDEO') {
setupVideo(node);
} else if (node.querySelector && node.querySelector('video')) {
setupVideo(node.querySelector('video'));
}
});
}
});
});
// Start observing the document body for DOM changes
observer.observe(document.body, {
childList: true,
subtree: true
});
// Initial checks
hideElementsByClass('ytd-watch-next-secondary-results-renderer');
hideElementById('comments');
// Initial video check
const initialVideo = document.querySelector('video');
if (initialVideo) {
setupVideo(initialVideo);
}
})();