Skip to content

Instantly share code, notes, and snippets.

@affan2021shaikh
Last active April 24, 2026 01:22
Show Gist options
  • Select an option

  • Save affan2021shaikh/efa8b9f8c31b794d2d3b2a1b99928e0f to your computer and use it in GitHub Desktop.

Select an option

Save affan2021shaikh/efa8b9f8c31b794d2d3b2a1b99928e0f to your computer and use it in GitHub Desktop.
// ==UserScript==
// @name Dark Reader Everywhere
// @namespace https://affan2021shaikh/
// @version 2.0
// @description Apply Dark Reader to every webpage with a small built-in control panel.
// @match *://*/*
// @run-at document-start
// @noframes
// @grant none
// ==/UserScript==
(() => {
'use strict';
const STORAGE_KEY = 'dr_everywhere_settings_v2';
const PANEL_ID = 'dr-everywhere-panel';
const BUTTON_ID = 'dr-everywhere-button';
const STYLE_ID = 'dr-everywhere-style';
const LIB_URLS = [
'https://cdn.jsdelivr.net/npm/darkreader@latest/darkreader.min.js',
'https://unpkg.com/darkreader@latest/darkreader.min.js'
];
const DEFAULTS = {
enabled: true,
mode: 'enable', // "enable" or "auto"
brightness: 100,
contrast: 90,
sepia: 10
};
let settings = loadSettings();
let libLoadPromise = null;
let panelOpen = false;
function loadSettings() {
try {
const raw = localStorage.getItem(STORAGE_KEY);
if (!raw) return { ...DEFAULTS };
const parsed = JSON.parse(raw);
return {
...DEFAULTS,
...parsed,
enabled: !!parsed.enabled,
mode: parsed.mode === 'auto' ? 'auto' : 'enable',
brightness: clampNumber(parsed.brightness, 0, 200, DEFAULTS.brightness),
contrast: clampNumber(parsed.contrast, 0, 200, DEFAULTS.contrast),
sepia: clampNumber(parsed.sepia, 0, 100, DEFAULTS.sepia)
};
} catch {
return { ...DEFAULTS };
}
}
function saveSettings() {
localStorage.setItem(STORAGE_KEY, JSON.stringify(settings));
}
function clampNumber(value, min, max, fallback) {
const n = Number(value);
if (!Number.isFinite(n)) return fallback;
return Math.min(max, Math.max(min, n));
}
function wait(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function loadDarkReader() {
if (window.DarkReader) return window.DarkReader;
if (libLoadPromise) return libLoadPromise;
libLoadPromise = new Promise((resolve, reject) => {
let index = 0;
const tryNext = () => {
if (window.DarkReader) {
resolve(window.DarkReader);
return;
}
if (index >= LIB_URLS.length) {
reject(new Error('Failed to load Dark Reader from CDN.'));
return;
}
const src = LIB_URLS[index++];
const script = document.createElement('script');
script.src = src;
script.async = true;
script.referrerPolicy = 'no-referrer';
script.onload = () => {
if (window.DarkReader) resolve(window.DarkReader);
else tryNext();
};
script.onerror = () => {
script.remove();
tryNext();
};
(document.head || document.documentElement).appendChild(script);
};
tryNext();
});
return libLoadPromise;
}
async function applyDarkReader() {
try {
const DarkReader = await loadDarkReader();
const config = {
brightness: settings.brightness,
contrast: settings.contrast,
sepia: settings.sepia
};
if (!settings.enabled) {
DarkReader.disable();
} else if (settings.mode === 'auto') {
DarkReader.auto(config);
} else {
DarkReader.enable(config);
}
updateStatusText();
updateButtonText();
} catch (err) {
console.warn('[Dark Reader Everywhere] Could not load Dark Reader:', err);
updateStatusText('Load failed');
updateButtonText();
}
}
function setEnabled(value) {
settings.enabled = !!value;
saveSettings();
applyDarkReader();
syncPanelFields();
}
function setMode(value) {
settings.mode = value === 'auto' ? 'auto' : 'enable';
saveSettings();
applyDarkReader();
syncPanelFields();
}
function setSetting(name, value) {
settings[name] = value;
saveSettings();
applyDarkReader();
syncPanelFields();
}
function ensureStyles() {
if (document.getElementById(STYLE_ID)) return;
const style = document.createElement('style');
style.id = STYLE_ID;
style.textContent = `
#${BUTTON_ID} {
position: fixed;
right: 14px;
bottom: 14px;
z-index: 2147483647;
border: 1px solid rgba(127,127,127,.35);
border-radius: 999px;
padding: 8px 12px;
font: 13px/1.2 system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
cursor: pointer;
background: rgba(20,20,20,.88);
color: #fff;
box-shadow: 0 6px 24px rgba(0,0,0,.25);
user-select: none;
}
#${PANEL_ID} {
position: fixed;
right: 14px;
bottom: 56px;
z-index: 2147483647;
width: 300px;
max-width: calc(100vw - 28px);
background: rgba(20,20,20,.96);
color: #fff;
border: 1px solid rgba(127,127,127,.35);
border-radius: 16px;
box-shadow: 0 14px 40px rgba(0,0,0,.35);
padding: 14px;
font: 13px/1.35 system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}
#${PANEL_ID} * {
box-sizing: border-box;
}
#${PANEL_ID} .dr-row {
margin: 10px 0;
}
#${PANEL_ID} .dr-title {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
font-weight: 700;
font-size: 14px;
margin-bottom: 10px;
}
#${PANEL_ID} .dr-close {
border: 0;
border-radius: 8px;
padding: 4px 8px;
cursor: pointer;
background: rgba(255,255,255,.12);
color: #fff;
}
#${PANEL_ID} label {
display: block;
margin-bottom: 5px;
opacity: .9;
}
#${PANEL_ID} input[type="range"] {
width: 100%;
}
#${PANEL_ID} select,
#${PANEL_ID} input[type="checkbox"] {
vertical-align: middle;
}
#${PANEL_ID} .dr-inline {
display: flex;
align-items: center;
justify-content: space-between;
gap: 10px;
}
#${PANEL_ID} .dr-small {
opacity: .8;
font-size: 12px;
}
#${PANEL_ID} .dr-actions {
display: flex;
gap: 8px;
margin-top: 12px;
}
#${PANEL_ID} button {
border: 0;
border-radius: 10px;
padding: 8px 10px;
cursor: pointer;
background: rgba(255,255,255,.12);
color: #fff;
}
#${PANEL_ID} .dr-spacer {
height: 1px;
background: rgba(255,255,255,.1);
margin: 10px 0;
}
#${PANEL_ID} .dr-value {
font-variant-numeric: tabular-nums;
opacity: .9;
}
`;
(document.head || document.documentElement).appendChild(style);
}
function createUI() {
if (document.getElementById(BUTTON_ID)) return;
ensureStyles();
const button = document.createElement('button');
button.id = BUTTON_ID;
button.type = 'button';
button.textContent = 'Dark Reader';
button.addEventListener('click', () => togglePanel());
document.documentElement.appendChild(button);
const panel = document.createElement('div');
panel.id = PANEL_ID;
panel.style.display = 'none';
panel.innerHTML = `
<div class="dr-title">
<span>Dark Reader</span>
<button class="dr-close" type="button" aria-label="Close">✕</button>
</div>
<div class="dr-row dr-inline">
<label style="margin:0;">
<input id="dr-enabled" type="checkbox">
Enabled
</label>
<span id="dr-status" class="dr-small">Loading…</span>
</div>
<div class="dr-row">
<label for="dr-mode">Mode</label>
<select id="dr-mode" style="width:100%;padding:8px;border-radius:10px;border:1px solid rgba(255,255,255,.15);background:rgba(255,255,255,.08);color:#fff;">
<option value="enable">Always on</option>
<option value="auto">Follow system theme</option>
</select>
</div>
<div class="dr-spacer"></div>
<div class="dr-row">
<div class="dr-inline">
<label for="dr-brightness">Brightness</label>
<span class="dr-value" id="dr-brightness-value"></span>
</div>
<input id="dr-brightness" type="range" min="0" max="200" step="1">
</div>
<div class="dr-row">
<div class="dr-inline">
<label for="dr-contrast">Contrast</label>
<span class="dr-value" id="dr-contrast-value"></span>
</div>
<input id="dr-contrast" type="range" min="0" max="200" step="1">
</div>
<div class="dr-row">
<div class="dr-inline">
<label for="dr-sepia">Sepia</label>
<span class="dr-value" id="dr-sepia-value"></span>
</div>
<input id="dr-sepia" type="range" min="0" max="100" step="1">
</div>
<div class="dr-actions">
<button id="dr-toggle" type="button">Toggle</button>
<button id="dr-reset" type="button">Reset</button>
</div>
<div class="dr-row dr-small" style="margin-top:10px;">
Shortcut: Alt+Shift+D
</div>
`;
document.documentElement.appendChild(panel);
const closeBtn = panel.querySelector('.dr-close');
const enabledEl = panel.querySelector('#dr-enabled');
const modeEl = panel.querySelector('#dr-mode');
const brightnessEl = panel.querySelector('#dr-brightness');
const contrastEl = panel.querySelector('#dr-contrast');
const sepiaEl = panel.querySelector('#dr-sepia');
const brightnessValue = panel.querySelector('#dr-brightness-value');
const contrastValue = panel.querySelector('#dr-contrast-value');
const sepiaValue = panel.querySelector('#dr-sepia-value');
const statusEl = panel.querySelector('#dr-status');
const toggleBtn = panel.querySelector('#dr-toggle');
const resetBtn = panel.querySelector('#dr-reset');
closeBtn.addEventListener('click', () => togglePanel(false));
enabledEl.addEventListener('change', () => setEnabled(enabledEl.checked));
modeEl.addEventListener('change', () => setMode(modeEl.value));
brightnessEl.addEventListener('input', () => setSetting('brightness', clampNumber(brightnessEl.value, 0, 200, DEFAULTS.brightness)));
contrastEl.addEventListener('input', () => setSetting('contrast', clampNumber(contrastEl.value, 0, 200, DEFAULTS.contrast)));
sepiaEl.addEventListener('input', () => setSetting('sepia', clampNumber(sepiaEl.value, 0, 100, DEFAULTS.sepia)));
toggleBtn.addEventListener('click', () => setEnabled(!settings.enabled));
resetBtn.addEventListener('click', () => {
settings = { ...DEFAULTS };
saveSettings();
syncPanelFields();
applyDarkReader();
});
function updateStatusText(text) {
statusEl.textContent = text || (settings.enabled ? 'On' : 'Off');
}
function updateButtonText() {
button.textContent = settings.enabled ? 'Dark Reader ✓' : 'Dark Reader';
}
function syncPanelFields() {
enabledEl.checked = settings.enabled;
modeEl.value = settings.mode;
brightnessEl.value = String(settings.brightness);
contrastEl.value = String(settings.contrast);
sepiaEl.value = String(settings.sepia);
brightnessValue.textContent = String(settings.brightness);
contrastValue.textContent = String(settings.contrast);
sepiaValue.textContent = String(settings.sepia);
updateStatusText();
updateButtonText();
}
window.__dr_everywhere_ui = {
panel,
button,
syncPanelFields,
updateStatusText,
updateButtonText
};
syncPanelFields();
}
function syncPanelFields() {
const ui = window.__dr_everywhere_ui;
if (ui && ui.syncPanelFields) ui.syncPanelFields();
}
function updateStatusText(text) {
const ui = window.__dr_everywhere_ui;
if (ui && ui.updateStatusText) ui.updateStatusText(text);
}
function updateButtonText() {
const ui = window.__dr_everywhere_ui;
if (ui && ui.updateButtonText) ui.updateButtonText();
}
function togglePanel(force) {
createUI();
const ui = window.__dr_everywhere_ui;
if (!ui) return;
panelOpen = typeof force === 'boolean' ? force : !panelOpen;
ui.panel.style.display = panelOpen ? 'block' : 'none';
}
function installKeyboardShortcuts() {
window.addEventListener('keydown', (e) => {
if (e.altKey && e.shiftKey && e.code === 'KeyD') {
e.preventDefault();
setEnabled(!settings.enabled);
}
if (e.altKey && e.shiftKey && e.code === 'KeyS') {
e.preventDefault();
togglePanel();
}
if (e.key === 'Escape' && panelOpen) {
togglePanel(false);
}
}, true);
}
async function init() {
createUI();
installKeyboardShortcuts();
// Give the page a moment to build its DOM, then apply the theme.
await wait(0);
await applyDarkReader();
// Re-apply if the page changes heavily and the library is already loaded.
const observer = new MutationObserver(() => {
if (settings.enabled && window.DarkReader) {
// Keep this lightweight: just ensure it stays on.
if (!window.DarkReader.isEnabled || !window.DarkReader.isEnabled()) {
applyDarkReader();
}
}
});
observer.observe(document.documentElement, { childList: true, subtree: true });
window.addEventListener('beforeunload', () => {
try {
observer.disconnect();
} catch {}
});
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', init, { once: true });
} else {
init();
}
})();
// ==UserScript==
// @name YouTube Background Play Max
// @namespace https://example.invalid/
// @version 3.0.0
// @description Best-effort background play for YouTube desktop and mobile web using only standard userscript features.
// @match https://www.youtube.com/*
// @match https://m.youtube.com/*
// @run-at document-start
// @grant none
// @noframes
// ==/UserScript==
(() => {
'use strict';
const CFG = {
debug: false,
manualGraceMs: 1200,
hiddenRetryMs: 200,
visibleRetryMs: 350,
maxRetryMs: 5000,
hiddenRetryWindowMs: 30000,
visibilitySpoof: true,
mediaSession: true,
audioKeepalive: true,
pipFallback: true,
mutedFallback: true,
pipRetryCooldownMs: 15000,
mutedRetryCooldownMs: 10000,
restoreMuteAfterMs: 1200,
};
const log = (...args) => {
if (CFG.debug) console.log('[YT BG Play Max]', ...args);
};
const SEL = [
'#movie_player video',
'ytd-player video',
'video.html5-main-video',
'video',
];
const CONTROL_SEL = [
'.ytp-play-button',
'.ytp-big-mode-play-button',
'button',
'[role="button"]',
'tp-yt-paper-icon-button',
'yt-icon-button',
].join(',');
const STATE = {
currentVideo: null,
desiredPlaying: false,
lastGestureAt: 0,
lastExplicitPlayPauseAt: 0,
lastManualPauseAt: 0,
hiddenSince: 0,
retryTimer: 0,
retryDelay: CFG.visibleRetryMs,
playInFlight: false,
booted: false,
observerStarted: false,
frameLoopStarted: false,
failures: 0,
lastPipAttemptAt: 0,
lastMutedFallbackAt: 0,
media: {
ctx: null,
oscillator: null,
gain: null,
unlocked: false,
},
originals: {
hidden: null,
visibilityState: null,
webkitHidden: null,
webkitVisibilityState: null,
hasFocus: null,
},
};
const now = () => Date.now();
function isElement(v) {
return v && v.nodeType === 1;
}
function isTypingTarget(target) {
if (!isElement(target)) return false;
const tag = target.tagName;
return tag === 'INPUT' || tag === 'TEXTAREA' || tag === 'SELECT' || target.isContentEditable;
}
function getDescriptor(proto, prop) {
let p = proto;
while (p) {
const d = Object.getOwnPropertyDescriptor(p, prop);
if (d) return d;
p = Object.getPrototypeOf(p);
}
return null;
}
function readActualHidden() {
try {
const d = STATE.originals.hidden;
if (d && typeof d.get === 'function') return !!d.get.call(document);
} catch (_) {}
try {
const d = STATE.originals.webkitHidden;
if (d && typeof d.get === 'function') return !!d.get.call(document);
} catch (_) {}
try {
return document.visibilityState !== 'visible';
} catch (_) {
return false;
}
}
function readActualVisibilityState() {
try {
const d = STATE.originals.visibilityState;
if (d && typeof d.get === 'function') return String(d.get.call(document));
} catch (_) {}
try {
const d = STATE.originals.webkitVisibilityState;
if (d && typeof d.get === 'function') return String(d.get.call(document));
} catch (_) {}
return readActualHidden() ? 'hidden' : 'visible';
}
function isActuallyHidden() {
return readActualVisibilityState() !== 'visible';
}
function installVisibilitySpoof() {
if (!CFG.visibilitySpoof) return;
const proto = Document.prototype;
STATE.originals.hidden = getDescriptor(proto, 'hidden');
STATE.originals.visibilityState = getDescriptor(proto, 'visibilityState');
STATE.originals.webkitHidden = getDescriptor(proto, 'webkitHidden');
STATE.originals.webkitVisibilityState = getDescriptor(proto, 'webkitVisibilityState');
STATE.originals.hasFocus = getDescriptor(proto, 'hasFocus');
const installGetter = (prop, getter, original) => {
try {
if (original && original.configurable === false) return false;
Object.defineProperty(proto, prop, {
configurable: true,
enumerable: original ? !!original.enumerable : false,
get: getter,
});
return true;
} catch (_) {
return false;
}
};
installGetter('hidden', function () {
return false;
}, STATE.originals.hidden);
installGetter('visibilityState', function () {
return 'visible';
}, STATE.originals.visibilityState);
installGetter('webkitHidden', function () {
return false;
}, STATE.originals.webkitHidden);
installGetter('webkitVisibilityState', function () {
return 'visible';
}, STATE.originals.webkitVisibilityState);
try {
const original = STATE.originals.hasFocus;
if (!original || original.configurable !== false) {
Object.defineProperty(proto, 'hasFocus', {
configurable: true,
enumerable: original ? !!original.enumerable : false,
writable: true,
value: function () {
return true;
},
});
}
} catch (_) {}
}
function setMediaSessionState() {
if (!CFG.mediaSession) return;
try {
if (!('mediaSession' in navigator)) return;
navigator.mediaSession.playbackState = STATE.desiredPlaying ? 'playing' : 'paused';
} catch (_) {}
}
function stopKeepaliveAudio() {
const m = STATE.media;
try {
if (m.ctx && m.ctx.state === 'running') {
m.ctx.suspend().catch(() => {});
}
} catch (_) {}
}
function startKeepaliveAudio() {
if (!CFG.audioKeepalive) return;
if (!STATE.desiredPlaying) return;
if (!isActuallyHidden()) {
stopKeepaliveAudio();
return;
}
const m = STATE.media;
try {
const AudioCtx = window.AudioContext || window.webkitAudioContext;
if (!AudioCtx) return;
if (!m.ctx) {
m.ctx = new AudioCtx();
m.gain = m.ctx.createGain();
m.gain.gain.value = 0.00001;
m.oscillator = m.ctx.createOscillator();
m.oscillator.type = 'sine';
m.oscillator.frequency.value = 40;
m.oscillator.connect(m.gain);
m.gain.connect(m.ctx.destination);
m.oscillator.start();
}
if (m.ctx.state === 'suspended') {
m.ctx.resume().catch(() => {});
}
} catch (_) {}
}
function unlockKeepaliveAudio() {
if (!CFG.audioKeepalive) return;
const m = STATE.media;
m.unlocked = true;
if (m.ctx && m.ctx.state === 'suspended') {
m.ctx.resume().catch(() => {});
}
}
function maybeStartKeepaliveAudio() {
if (!CFG.audioKeepalive) return;
if (!STATE.media.unlocked) return;
startKeepaliveAudio();
}
function setDesiredPlaying(next, reason) {
const changed = STATE.desiredPlaying !== next;
STATE.desiredPlaying = next;
if (next) {
setMediaSessionState();
maybeStartKeepaliveAudio();
if (changed) scheduleRetry(reason || 'intent', true);
} else {
setMediaSessionState();
stopKeepaliveAudio();
clearTimeout(STATE.retryTimer);
}
}
function manualGraceActive() {
const t = now();
const recent = Math.max(STATE.lastGestureAt, STATE.lastExplicitPlayPauseAt, STATE.lastManualPauseAt);
return (t - recent) <= CFG.manualGraceMs;
}
function touchGesture(event) {
STATE.lastGestureAt = now();
if (isTypingTarget(event && event.target)) return;
unlockKeepaliveAudio();
}
function inferControlIntent(event) {
const target = event && event.target;
if (!isElement(target)) return null;
const control = target.closest('.ytp-play-button, .ytp-big-mode-play-button');
if (control) {
const label = [
control.getAttribute('aria-label'),
control.getAttribute('title'),
control.getAttribute('data-title-no-tooltip'),
control.textContent,
].filter(Boolean).join(' ').toLowerCase();
if (label.includes('pause') && !label.includes('play')) return 'pause';
if (label.includes('play') && !label.includes('pause')) return 'play';
if (STATE.currentVideo) {
return STATE.currentVideo.paused ? 'play' : 'pause';
}
}
return null;
}
function onPointerLike(event) {
touchGesture(event);
const intent = inferControlIntent(event);
if (intent === 'play') {
STATE.lastExplicitPlayPauseAt = now();
setDesiredPlaying(true, 'user-play');
} else if (intent === 'pause') {
STATE.lastExplicitPlayPauseAt = now();
STATE.lastManualPauseAt = now();
setDesiredPlaying(false, 'user-pause');
}
}
function onKeydown(event) {
if (event.repeat) return;
if (isTypingTarget(event.target)) return;
touchGesture(event);
const key = String(event.key || '').toLowerCase();
const mediaKey = key === 'mediaplaypause' || key === 'mediaplay' || key === 'play';
const pauseKey = key === 'mediapause';
if (mediaKey) {
STATE.lastExplicitPlayPauseAt = now();
setDesiredPlaying(true, 'media-key-play');
return;
}
if (pauseKey) {
STATE.lastExplicitPlayPauseAt = now();
STATE.lastManualPauseAt = now();
setDesiredPlaying(false, 'media-key-pause');
return;
}
if (key === ' ' || key === 'spacebar' || key === 'k') {
STATE.lastExplicitPlayPauseAt = now();
if (STATE.currentVideo && !STATE.currentVideo.paused) {
STATE.lastManualPauseAt = now();
setDesiredPlaying(false, 'toggle-pause');
} else {
setDesiredPlaying(true, 'toggle-play');
}
}
}
function scoreVideo(v) {
if (!(v instanceof HTMLVideoElement) || !v.isConnected) return -1e18;
const r = v.getBoundingClientRect();
const area = Math.max(0, r.width) * Math.max(0, r.height);
let score = area;
if (r.width > 0 && r.height > 0) score += 1_000_000;
if (!v.paused) score += 250_000;
if (v.readyState >= 2) score += 15_000;
if (v.currentSrc) score += 5_000;
if (document.body && document.body.contains(v)) score += 2_000;
if (v.matches('.html5-main-video')) score += 250_000;
if (v.closest('#movie_player')) score += 175_000;
if (v.closest('ytd-player')) score += 125_000;
if (v.closest('.html5-video-container')) score += 75_000;
return score;
}
function pickVideo() {
const seen = new Set();
const candidates = [];
for (const sel of SEL) {
for (const v of document.querySelectorAll(sel)) {
if (!seen.has(v)) {
seen.add(v);
candidates.push(v);
}
}
}
let best = null;
let bestScore = -1e18;
for (const v of candidates) {
const s = scoreVideo(v);
if (s > bestScore) {
bestScore = s;
best = v;
}
}
return best;
}
function attachVideo(v) {
if (!(v instanceof HTMLVideoElement)) return;
if (v === STATE.currentVideo) return;
if (STATE.currentVideo) {
STATE.currentVideo.removeEventListener('play', onPlay, true);
STATE.currentVideo.removeEventListener('playing', onPlaying, true);
STATE.currentVideo.removeEventListener('pause', onPause, true);
STATE.currentVideo.removeEventListener('ended', onEnded, true);
STATE.currentVideo.removeEventListener('emptied', onVideoSourceChange, true);
STATE.currentVideo.removeEventListener('loadstart', onVideoSourceChange, true);
STATE.currentVideo.removeEventListener('loadedmetadata', onVideoSourceChange, true);
STATE.currentVideo.removeEventListener('stalled', onNeedRetry, true);
STATE.currentVideo.removeEventListener('waiting', onNeedRetry, true);
STATE.currentVideo.removeEventListener('suspend', onNeedRetry, true);
STATE.currentVideo.removeEventListener('canplay', onNeedRetry, true);
}
STATE.currentVideo = v;
try {
STATE.currentVideo.setAttribute('playsinline', '');
STATE.currentVideo.setAttribute('webkit-playsinline', '');
} catch (_) {}
STATE.currentVideo.addEventListener('play', onPlay, true);
STATE.currentVideo.addEventListener('playing', onPlaying, true);
STATE.currentVideo.addEventListener('pause', onPause, true);
STATE.currentVideo.addEventListener('ended', onEnded, true);
STATE.currentVideo.addEventListener('emptied', onVideoSourceChange, true);
STATE.currentVideo.addEventListener('loadstart', onVideoSourceChange, true);
STATE.currentVideo.addEventListener('loadedmetadata', onVideoSourceChange, true);
STATE.currentVideo.addEventListener('stalled', onNeedRetry, true);
STATE.currentVideo.addEventListener('waiting', onNeedRetry, true);
STATE.currentVideo.addEventListener('suspend', onNeedRetry, true);
STATE.currentVideo.addEventListener('canplay', onNeedRetry, true);
log('attached video');
}
function syncVideo() {
const best = pickVideo();
if (best) attachVideo(best);
}
function resetRetryDelay() {
STATE.retryDelay = isActuallyHidden() ? CFG.hiddenRetryMs : CFG.visibleRetryMs;
}
function bumpRetryDelay() {
STATE.retryDelay = Math.min(Math.max(STATE.retryDelay * 1.5, 200), CFG.maxRetryMs);
}
async function tryPictureInPicture(reason) {
if (!CFG.pipFallback) return false;
if (!STATE.currentVideo || !STATE.desiredPlaying) return false;
if (!STATE.currentVideo.isConnected) return false;
if (!(location.hostname.startsWith('m.') || matchMedia('(pointer: coarse)').matches)) return false;
if (!document.pictureInPictureEnabled) return false;
if (document.pictureInPictureElement === STATE.currentVideo) return true;
if (STATE.currentVideo.disablePictureInPicture) return false;
const t = now();
if (t - STATE.lastPipAttemptAt < CFG.pipRetryCooldownMs) return false;
STATE.lastPipAttemptAt = t;
try {
if (typeof STATE.currentVideo.requestPictureInPicture !== 'function') return false;
await STATE.currentVideo.requestPictureInPicture();
log('pip ok', reason);
return true;
} catch (err) {
log('pip failed', reason, err && err.name ? err.name : err);
return false;
}
}
async function tryMutedFallback(reason) {
if (!CFG.mutedFallback) return false;
if (!STATE.currentVideo || !STATE.desiredPlaying) return false;
if (!STATE.currentVideo.isConnected) return false;
if (STATE.currentVideo.muted) return false;
const t = now();
if (t - STATE.lastMutedFallbackAt < CFG.mutedRetryCooldownMs) return false;
STATE.lastMutedFallbackAt = t;
const prevMuted = STATE.currentVideo.muted;
const prevVolume = STATE.currentVideo.volume;
try {
STATE.currentVideo.muted = true;
const p = STATE.currentVideo.play();
if (p && typeof p.then === 'function') {
await p;
}
setTimeout(() => {
try {
if (!STATE.currentVideo || STATE.currentVideo.paused) return;
if (!STATE.desiredPlaying) return;
STATE.currentVideo.muted = prevMuted;
STATE.currentVideo.volume = prevVolume;
} catch (_) {}
}, CFG.restoreMuteAfterMs);
log('muted fallback ok', reason);
return true;
} catch (err) {
try {
if (STATE.currentVideo) {
STATE.currentVideo.muted = prevMuted;
STATE.currentVideo.volume = prevVolume;
}
} catch (_) {}
log('muted fallback failed', reason, err && err.name ? err.name : err);
return false;
}
}
async function safePlay(reason) {
if (!STATE.currentVideo || !STATE.desiredPlaying) return false;
if (STATE.playInFlight) return true;
STATE.playInFlight = true;
try {
if (!STATE.currentVideo.isConnected) {
syncVideo();
if (!STATE.currentVideo) return false;
}
if (!STATE.currentVideo.paused && STATE.currentVideo.readyState >= 2) {
STATE.failures = 0;
resetRetryDelay();
maybeStartKeepaliveAudio();
setMediaSessionState();
return true;
}
try {
const p = STATE.currentVideo.play();
if (p && typeof p.then === 'function') {
await p;
}
STATE.failures = 0;
resetRetryDelay();
maybeStartKeepaliveAudio();
setMediaSessionState();
log('play ok', reason);
return true;
} catch (err) {
log('play failed', reason, err && err.name ? err.name : err);
}
STATE.failures += 1;
bumpRetryDelay();
if (STATE.failures >= 2) {
const pipOk = await tryPictureInPicture(reason);
if (pipOk) {
STATE.failures = 0;
resetRetryDelay();
maybeStartKeepaliveAudio();
setMediaSessionState();
return true;
}
}
if (STATE.failures >= 3) {
const mutedOk = await tryMutedFallback(reason);
if (mutedOk) {
STATE.failures = 0;
resetRetryDelay();
maybeStartKeepaliveAudio();
setMediaSessionState();
return true;
}
}
return false;
} finally {
STATE.playInFlight = false;
}
}
function scheduleRetry(reason, immediate = false) {
if (!STATE.desiredPlaying) return;
clearTimeout(STATE.retryTimer);
const hidden = isActuallyHidden();
const delay = immediate ? 0 : (hidden ? STATE.hiddenRetryDelay || CFG.hiddenRetryMs : STATE.retryDelay);
STATE.retryTimer = setTimeout(async () => {
if (!STATE.desiredPlaying) return;
const stillHidden = isActuallyHidden();
if (stillHidden && STATE.hiddenSince && (now() - STATE.hiddenSince) > CFG.hiddenRetryWindowMs) {
return;
}
syncVideo();
if (!STATE.currentVideo) {
bumpRetryDelay();
scheduleRetry(reason);
return;
}
if (!STATE.currentVideo.paused && STATE.currentVideo.readyState >= 2) {
STATE.failures = 0;
resetRetryDelay();
maybeStartKeepaliveAudio();
return;
}
const ok = await safePlay(reason);
if (!ok && STATE.desiredPlaying) {
scheduleRetry(reason);
}
}, delay);
}
function onPlay() {
setDesiredPlaying(true, 'play-event');
}
function onPlaying() {
setDesiredPlaying(true, 'playing-event');
}
function onPause() {
if (manualGraceActive()) {
STATE.lastManualPauseAt = now();
setDesiredPlaying(false, 'manual-pause');
return;
}
if (STATE.desiredPlaying) {
scheduleRetry('pause', true);
}
}
function onEnded() {
setDesiredPlaying(false, 'ended');
}
function onVideoSourceChange() {
setTimeout(() => {
syncVideo();
if (STATE.desiredPlaying) scheduleRetry('source-change', true);
}, 0);
}
function onNeedRetry() {
if (STATE.desiredPlaying) scheduleRetry('buffering');
}
function onVisibilityChange() {
const hidden = isActuallyHidden();
if (hidden) {
STATE.hiddenSince = now();
if (STATE.desiredPlaying) {
maybeStartKeepaliveAudio();
scheduleRetry('hidden', true);
}
} else {
STATE.hiddenSince = 0;
if (STATE.desiredPlaying) {
stopKeepaliveAudio();
scheduleRetry('visible', true);
}
}
}
function onPageHide() {
STATE.hiddenSince = now();
if (STATE.desiredPlaying) scheduleRetry('pagehide', true);
}
function onPageShow() {
STATE.hiddenSince = 0;
if (STATE.desiredPlaying) scheduleRetry('pageshow', true);
}
function onFreeze() {
if (STATE.desiredPlaying) scheduleRetry('freeze', true);
}
function onResume() {
if (STATE.desiredPlaying) scheduleRetry('resume', true);
}
function patchPause() {
const proto = HTMLMediaElement && HTMLMediaElement.prototype;
if (!proto || typeof proto.pause !== 'function') return;
const nativePause = proto.pause;
proto.pause = function patchedPause() {
try {
if (
this === STATE.currentVideo &&
STATE.desiredPlaying &&
isActuallyHidden() &&
!manualGraceActive()
) {
log('blocked hidden pause');
return;
}
} catch (_) {}
return nativePause.apply(this, arguments);
};
}
function patchHistory() {
const dispatch = () => window.dispatchEvent(new Event('ytbg-locationchange'));
try {
const pushState = history.pushState;
if (typeof pushState === 'function') {
history.pushState = function () {
const ret = pushState.apply(this, arguments);
dispatch();
return ret;
};
}
} catch (_) {}
try {
const replaceState = history.replaceState;
if (typeof replaceState === 'function') {
history.replaceState = function () {
const ret = replaceState.apply(this, arguments);
dispatch();
return ret;
};
}
} catch (_) {}
window.addEventListener('popstate', dispatch, true);
window.addEventListener('yt-navigate-finish', dispatch, true);
window.addEventListener('yt-page-data-updated', dispatch, true);
window.addEventListener('ytbg-locationchange', () => {
setTimeout(() => {
syncVideo();
if (STATE.desiredPlaying) scheduleRetry('navigation', true);
}, 0);
}, true);
}
function startObserver() {
if (STATE.observerStarted) return;
const root = document.documentElement;
if (!root) return;
STATE.observerStarted = true;
const mo = new MutationObserver(() => {
syncVideo();
if (STATE.desiredPlaying && (!STATE.currentVideo || !STATE.currentVideo.isConnected)) {
scheduleRetry('mutation', true);
}
});
mo.observe(root, { childList: true, subtree: true });
syncVideo();
log('observer started');
}
function startFrameLoop() {
if (STATE.frameLoopStarted) return;
STATE.frameLoopStarted = true;
const tick = () => {
if (STATE.desiredPlaying) {
if (!STATE.currentVideo || !STATE.currentVideo.isConnected) {
syncVideo();
}
if (STATE.currentVideo) {
if (isActuallyHidden()) {
if (STATE.currentVideo.paused) scheduleRetry('frame-hidden');
} else if (STATE.currentVideo.paused) {
scheduleRetry('frame-visible');
}
}
}
requestAnimationFrame(tick);
};
requestAnimationFrame(tick);
}
function installMediaSessionHandlers() {
if (!CFG.mediaSession) return;
try {
if (!('mediaSession' in navigator)) return;
if (typeof navigator.mediaSession.setActionHandler !== 'function') return;
navigator.mediaSession.setActionHandler('play', () => {
setDesiredPlaying(true, 'mediasession-play');
});
navigator.mediaSession.setActionHandler('pause', () => {
STATE.lastManualPauseAt = now();
setDesiredPlaying(false, 'mediasession-pause');
});
navigator.mediaSession.setActionHandler('stop', () => {
STATE.lastManualPauseAt = now();
setDesiredPlaying(false, 'mediasession-stop');
});
} catch (_) {}
}
function installGlobalListeners() {
document.addEventListener('pointerdown', onPointerLike, true);
document.addEventListener('pointerup', onPointerLike, true);
document.addEventListener('click', onPointerLike, true);
document.addEventListener('touchstart', onPointerLike, true);
document.addEventListener('mousedown', onPointerLike, true);
document.addEventListener('keydown', onKeydown, true);
document.addEventListener('visibilitychange', onVisibilityChange, true);
window.addEventListener('pagehide', onPageHide, true);
window.addEventListener('pageshow', onPageShow, true);
window.addEventListener('freeze', onFreeze, true);
window.addEventListener('resume', onResume, true);
window.addEventListener('focus', onVisibilityChange, true);
window.addEventListener('blur', onVisibilityChange, true);
}
function boot() {
if (STATE.booted) return;
STATE.booted = true;
installVisibilitySpoof();
patchPause();
patchHistory();
installGlobalListeners();
installMediaSessionHandlers();
const tryStart = () => {
startObserver();
if (document.documentElement) startFrameLoop();
};
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', tryStart, { once: true });
} else {
tryStart();
}
setInterval(() => {
if (!STATE.desiredPlaying) return;
syncVideo();
if (!STATE.currentVideo) return;
if (isActuallyHidden()) {
if (STATE.currentVideo.paused) scheduleRetry('watchdog-hidden');
maybeStartKeepaliveAudio();
return;
}
if (STATE.currentVideo.paused) {
scheduleRetry('watchdog-visible');
} else {
STATE.failures = 0;
resetRetryDelay();
stopKeepaliveAudio();
}
}, 250);
}
boot();
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment