mirror of
https://github.com/Shik3i/KoalaSync.git
synced 2026-08-19 07:36:16 +00:00
36e1291d2c
The weighted score summed incomparable units, so size could outvote traits that disqualify an element outright. Measured on a real page: a display:none preload reports its full 1080p intrinsic size and scored 2073600, beating a visible unmuted player at 509920. Selection now compares an ordered list of signals, highest priority first: has a source, is rendered, is not a silent background loop, rendered size bucket, is playing, has controls, duration. Rendered size replaces intrinsic resolution, and mute state is gone from the ranking entirely: it is a viewer preference, not evidence about which element is the player. It stays a ranking rather than a filter, so a page of only bad candidates still yields one and findVideo never returns null where a video exists. The new tests/e2e suite runs the shipped finder against real fixture pages and drives the packed extension for injection, reinjection and remote play/pause/seek into a first-party frame. All five scoring scenarios fail against the previous implementation. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
52 lines
1.8 KiB
JavaScript
52 lines
1.8 KiB
JavaScript
/**
|
|
* Fixture helper. Marks the page ready once every <video> that is supposed to
|
|
* carry metadata has it, and once every video marked data-autoplay is actually
|
|
* playing. Tests wait for window.__fixtureReady instead of sleeping, so the
|
|
* scoring signals (videoWidth, duration, paused) are settled before we look.
|
|
*/
|
|
(function () {
|
|
window.__fixtureReady = false;
|
|
|
|
function collectVideos(doc, out) {
|
|
for (const video of doc.querySelectorAll('video')) out.push(video);
|
|
for (const frame of doc.querySelectorAll('iframe')) {
|
|
let frameDoc = null;
|
|
try { frameDoc = frame.contentDocument; } catch (_e) { frameDoc = null; }
|
|
if (frameDoc) collectVideos(frameDoc, out);
|
|
}
|
|
for (const host of doc.querySelectorAll('*')) {
|
|
if (host.shadowRoot) collectVideos(host.shadowRoot, out);
|
|
}
|
|
return out;
|
|
}
|
|
|
|
function metadataReady(video) {
|
|
if (video.dataset.sourceless !== undefined) return true;
|
|
return video.readyState >= 1;
|
|
}
|
|
|
|
function playbackReady(video) {
|
|
if (video.dataset.autoplay === undefined) return true;
|
|
return !video.paused;
|
|
}
|
|
|
|
function check() {
|
|
const videos = collectVideos(document, []);
|
|
if (!videos.length) return false;
|
|
if (!videos.every(v => metadataReady(v) && playbackReady(v))) return false;
|
|
window.__fixtureReady = true;
|
|
return true;
|
|
}
|
|
|
|
function start() {
|
|
for (const video of collectVideos(document, [])) {
|
|
if (video.dataset.autoplay !== undefined) video.play().catch(() => {});
|
|
}
|
|
if (check()) return;
|
|
const timer = setInterval(() => { if (check()) clearInterval(timer); }, 50);
|
|
}
|
|
|
|
if (document.readyState === 'complete') start();
|
|
else window.addEventListener('load', start);
|
|
})();
|