Instead of elements closer to the <video> tag, prefer best-matching element closer to page root.

This ensures UI always renders on top of player if enabled.
This commit is contained in:
Tamius Han 2025-03-31 23:26:03 +02:00
parent 5460719297
commit 7c1d3e52e5

View File

@ -699,6 +699,7 @@ class PlayerData {
let penaltyMultiplier = 1; let penaltyMultiplier = 1;
const sizePenaltyMultiplier = 0.1; const sizePenaltyMultiplier = 0.1;
const perLevelScorePenalty = 10; const perLevelScorePenalty = 10;
let sameSizeBonus = 0;
for (const [index, element] of elementStack.entries()) { for (const [index, element] of elementStack.entries()) {
element.index = index; element.index = index;
@ -747,7 +748,13 @@ class PlayerData {
// we prefer elements closer to the video, so the score of each potential // we prefer elements closer to the video, so the score of each potential
// candidate gets dinked a bit // candidate gets dinked a bit
score -= perLevelScorePenalty * penaltyMultiplier; // score -= perLevelScorePenalty * penaltyMultiplier;
if (element.width === elementStack[index - 1].width && element.height === elementStack[index - 1].height) {
score += ++sameSizeBonus;
} else {
sameSizeBonus = 0;
}
element.autoScore = score; element.autoScore = score;
element.heuristics['autoScoreDetails'] = { element.heuristics['autoScoreDetails'] = {
@ -762,12 +769,14 @@ class PlayerData {
} }
} }
let bestCandidate: any = {autoScore: -99999999, initialValue: true}; let bestCandidate: any = {autoScore: -99999999, initialValue: true};
for (const element of elementStack) { for (const element of elementStack) {
if (element.autoScore > bestCandidate.autoScore) { if (element.autoScore > bestCandidate.autoScore) {
bestCandidate = element; bestCandidate = element;
} }
} }
if (bestCandidate.initialValue) { if (bestCandidate.initialValue) {
bestCandidate = null; bestCandidate = null;
} else { } else {
@ -777,6 +786,22 @@ class PlayerData {
} }
} }
// BUT WAIT! THERE'S MORE
// Some sites (youtube) can re-parent elements, causing current player element to vanish from DOM
if (bestCandidate) {
const observer = new MutationObserver( (mutations) => {
mutations.forEach((mutation) => {
mutation.removedNodes.forEach((node) => {
if (node === bestCandidate.element) {
observer.disconnect();
this.updatePlayer();
}
})
});
});
observer.observe(bestCandidate.element.parentNode, {childList: true});
}
return bestCandidate; return bestCandidate;
} }