Apple tv plus (#541)

* add support for traversing shadowRoot's; enables apple tv support.
This commit is contained in:
jedawson
2020-02-06 16:07:33 -06:00
committed by GitHub
parent 0389c61db7
commit 4ac2e458f5

View File

@@ -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,6 +453,8 @@
// Process the DOM nodes lazily // Process the DOM nodes lazily
requestIdleCallback(_ => { requestIdleCallback(_ => {
mutations.forEach(function(mutation) { mutations.forEach(function(mutation) {
switch (mutation.type) {
case 'childList':
forEach.call(mutation.addedNodes, function(node) { forEach.call(mutation.addedNodes, function(node) {
if (typeof node === "function") if (typeof node === "function")
return; return;
@@ -434,10 +465,29 @@
return; return;
checkForVideo(node, node.parentNode || mutation.target, false); 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;