Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Explosion-Scratch/061ed67bd292e07fbd018cc7ddbdce8d to your computer and use it in GitHub Desktop.
Save Explosion-Scratch/061ed67bd292e07fbd018cc7ddbdce8d to your computer and use it in GitHub Desktop.
// ==UserScript==
// @name Auto Picture-in-Picture
// @namespace mailto:explosionscratch@gmail.com
// @version 0.1
// @description Auto picture in picture for YouTube
// @author Explosion-Scratch
// @match *://youtube.*/*
// @grant none
// ==/UserScript==
/* Copyright (C) Mar 29, 2024 Explosion-Scratch - All Rights Reserved
* You may use, distribute and modify this code under the
* terms of the Attribution-ShareAlike 4.0 International license.
*
* You should have received a copy of the Attribution-ShareAlike
* 4.0 International license with this file. If not, please write
* to: explosionscatch@gmail.com, or visit:
* https://creativecommons.org/licenses/by-sa/4.0/
*/
const getVideo = () =>
[...document.querySelectorAll("video")].filter((i) => {
let rect = i.getBoundingClientRect();
return (
rect.width * rect.height > window.innerWidth * window.innerHeight * 0.2 &&
!i.paused &&
!i.mute
);
})?.[0];
let isBlurred = false;
const listeners = {
blur: (vid) => {
vid.requestPictureInPicture();
},
focus: (vid) => {
document.exitPictureInPicture();
},
};
const cb = () => {
const vid = getVideo();
if (!vid) {
return;
}
window.onblur = () => listeners.blur(vid);
window.onfocus = () => listeners.focus(vid);
};
observe("body", cb);
cb();
function observe(target, callback, options = {}) {
let elements = [];
if (typeof target === "string") {
elements = Array.from(document.querySelectorAll(target));
} else if (target instanceof Element) {
elements = [target];
} else {
throw new Error(
"Invalid target. Expected a query selector string or an Element."
);
}
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
callback(mutation.target, options);
});
});
const defaultOptions = {
childList: true,
attributes: true,
characterData: true,
subtree: true,
};
const observerOptions = { ...defaultOptions, ...options };
elements.forEach((element) => {
observer.observe(element, observerOptions);
});
return observer;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment