mirror of
https://github.com/SoPat712/videospeed.git
synced 2025-08-21 18:08:46 -04:00
Apple tv plus (#541)
* add support for traversing shadowRoot's; enables apple tv support.
This commit is contained in:
85
inject.js
85
inject.js
@@ -180,7 +180,7 @@
|
|||||||
var observer=new MutationObserver((mutations) => {
|
var observer=new MutationObserver((mutations) => {
|
||||||
mutations.forEach((mutation) => {
|
mutations.forEach((mutation) => {
|
||||||
if (mutation.type === 'attributes' && (mutation.attributeName === 'src' || mutation.attributeName === 'currentSrc')){
|
if (mutation.type === 'attributes' && (mutation.attributeName === 'src' || mutation.attributeName === 'currentSrc')){
|
||||||
var controller = document.querySelector(`div[data-vscid="${this.id}"]`);
|
var controller = getController(this.id)
|
||||||
if(!controller){
|
if(!controller){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -268,6 +268,9 @@
|
|||||||
// insert before parent to bypass overlay
|
// insert before parent to bypass overlay
|
||||||
this.parent.parentElement.insertBefore(fragment, this.parent);
|
this.parent.parentElement.insertBefore(fragment, this.parent);
|
||||||
break;
|
break;
|
||||||
|
case (location.hostname == 'tv.apple.com'):
|
||||||
|
// insert after parent for correct stacking context
|
||||||
|
this.parent.getRootNode().querySelector('.scrim').prepend(fragment);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// Note: when triggered via a MutationRecord, it's possible that the
|
// Note: when triggered via a MutationRecord, it's possible that the
|
||||||
@@ -333,6 +336,32 @@
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
function getShadow(parent) {
|
||||||
|
let result = []
|
||||||
|
function getChild(parent) {
|
||||||
|
if (parent.firstElementChild) {
|
||||||
|
var child = parent.firstElementChild
|
||||||
|
do {
|
||||||
|
result = result.concat(child)
|
||||||
|
getChild(child)
|
||||||
|
if (child.shadowRoot) {
|
||||||
|
result = result.concat(getShadow(child.shadowRoot))
|
||||||
|
}
|
||||||
|
child = child.nextElementSibling
|
||||||
|
} while (child)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
getChild(parent)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
function getController(id){
|
||||||
|
return getShadow(document.body).filter(x => {
|
||||||
|
return x.attributes['data-vscid'] &&
|
||||||
|
x.tagName == 'DIV' &&
|
||||||
|
x.attributes['data-vscid'].value==`${id}`
|
||||||
|
})[0]
|
||||||
|
}
|
||||||
|
|
||||||
function initializeNow(document) {
|
function initializeNow(document) {
|
||||||
if (!tc.settings.enabled) return;
|
if (!tc.settings.enabled) return;
|
||||||
// enforce init-once due to redundant callers
|
// enforce init-once due to redundant callers
|
||||||
@@ -380,7 +409,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Ignore keydown event if typing in a page without vsc
|
// Ignore keydown event if typing in a page without vsc
|
||||||
if (!document.querySelector(".vsc-controller")) {
|
if (!getShadow(document.body).filter(x => x.tagName == 'vsc-controller')) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -424,20 +453,41 @@
|
|||||||
// Process the DOM nodes lazily
|
// Process the DOM nodes lazily
|
||||||
requestIdleCallback(_ => {
|
requestIdleCallback(_ => {
|
||||||
mutations.forEach(function(mutation) {
|
mutations.forEach(function(mutation) {
|
||||||
forEach.call(mutation.addedNodes, function(node) {
|
switch (mutation.type) {
|
||||||
if (typeof node === "function")
|
case 'childList':
|
||||||
return;
|
forEach.call(mutation.addedNodes, function(node) {
|
||||||
checkForVideo(node, node.parentNode || mutation.target, true);
|
if (typeof node === "function")
|
||||||
});
|
return;
|
||||||
forEach.call(mutation.removedNodes, function(node) {
|
checkForVideo(node, node.parentNode || mutation.target, true);
|
||||||
if (typeof node === "function")
|
});
|
||||||
return;
|
forEach.call(mutation.removedNodes, function(node) {
|
||||||
checkForVideo(node, node.parentNode || mutation.target, false);
|
if (typeof node === "function")
|
||||||
});
|
return;
|
||||||
|
checkForVideo(node, node.parentNode || mutation.target, false);
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
case 'attributes':
|
||||||
|
if (mutation.target.attributes['aria-hidden'].value == "false") {
|
||||||
|
var flattenedNodes = getShadow(document.body)
|
||||||
|
var node = flattenedNodes.filter(x => x.tagName == 'VIDEO')[0]
|
||||||
|
if (node) {
|
||||||
|
var oldController = flattenedNodes.filter(x => x.classList.contains('vsc-controller'))[0]
|
||||||
|
if (oldController) {
|
||||||
|
oldController.remove()
|
||||||
|
}
|
||||||
|
checkForVideo(node, node.parentNode || mutation.target, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
};
|
||||||
});
|
});
|
||||||
}, {timeout: 1000});
|
}, {timeout: 1000});
|
||||||
});
|
});
|
||||||
observer.observe(document, { childList: true, subtree: true });
|
observer.observe(document, {
|
||||||
|
attributeFilter: ['aria-hidden'],
|
||||||
|
childList: true,
|
||||||
|
subtree: true
|
||||||
|
});
|
||||||
|
|
||||||
if (tc.settings.audioBoolean) {
|
if (tc.settings.audioBoolean) {
|
||||||
var mediaTags = document.querySelectorAll('video,audio');
|
var mediaTags = document.querySelectorAll('video,audio');
|
||||||
@@ -459,9 +509,11 @@
|
|||||||
|
|
||||||
function runAction(action, document, value, e) {
|
function runAction(action, document, value, e) {
|
||||||
if (tc.settings.audioBoolean) {
|
if (tc.settings.audioBoolean) {
|
||||||
var mediaTags = document.querySelectorAll('video,audio');
|
var mediaTags = getShadow(document.body).filter(x => {
|
||||||
|
return x.tagName == 'AUDIO' || x.tagName == 'VIDEO'
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
var mediaTags = document.querySelectorAll('video');
|
var mediaTags = getShadow(document.body).filter(x => x.tagName == 'VIDEO');
|
||||||
}
|
}
|
||||||
|
|
||||||
mediaTags.forEach = Array.prototype.forEach;
|
mediaTags.forEach = Array.prototype.forEach;
|
||||||
@@ -473,8 +525,7 @@
|
|||||||
|
|
||||||
mediaTags.forEach(function(v) {
|
mediaTags.forEach(function(v) {
|
||||||
var id = v.dataset['vscid'];
|
var id = v.dataset['vscid'];
|
||||||
var controller = document.querySelector(`div[data-vscid="${id}"]`);
|
var controller = getController(id)
|
||||||
|
|
||||||
// Don't change video speed if the video has a different controller
|
// Don't change video speed if the video has a different controller
|
||||||
if (e && !(targetController == controller)) {
|
if (e && !(targetController == controller)) {
|
||||||
return;
|
return;
|
||||||
|
Reference in New Issue
Block a user