fix(extension): preserve media detection across scrolling

This commit is contained in:
KoalaDev
2026-08-17 17:04:05 +02:00
parent 082b69f509
commit 0701d347c7
5 changed files with 104 additions and 18 deletions
+14 -4
View File
@@ -681,12 +681,22 @@
if (intent === 'involuntary') {
// EC-4 loop guard: only the silent auto snap-back is suppressed by the
// cooldown — the deliberate dialog path below must still go through,
// otherwise a second deliberate pause inside the cooldown window leaves
// cooldown — the deliberate dialog path below must still go through,
// otherwise a second deliberate pause inside the cooldown window leaves
// the user stuck paused with no UI (M-3).
if (Date.now() < hcmSnapBackCooldownUntil || hcmDeferredSnapPending) return;
// Buffering/ads/throttle — silently re-sync, no dialog spam.
const video = findVideo();
if (video && video.readyState >= 3 && !video.seeking) {
// Ready now → snap immediately. Use the captured target if it's
// usable, otherwise re-query+retry (host state may not be known yet)
+8 -4
View File
@@ -44,12 +44,16 @@
const browserReportsVisible = typeof element.checkVisibility === 'function'
? element.checkVisibility({ checkOpacity: true, checkVisibilityCSS: true })
: true;
const layoutWidth = Math.max(window.innerWidth, document.documentElement?.scrollWidth || 0);
const layoutHeight = Math.max(window.innerHeight, document.documentElement?.scrollHeight || 0);
const scrollX = Number(window.scrollX) || 0;
const scrollY = Number(window.scrollY) || 0;
const visible = rect.width > 0
&& rect.height > 0
&& rect.bottom > 0
&& rect.right > 0
&& rect.top < window.innerHeight
&& rect.left < window.innerWidth
&& rect.bottom + scrollY > 0
&& rect.right + scrollX > 0
&& rect.top + scrollY < layoutHeight
&& rect.left + scrollX < layoutWidth
&& browserReportsVisible
&& elementStylesAllowRendering(element)
&& style.display !== 'none'
+17 -9
View File
@@ -61,10 +61,14 @@ export function inspectMediaFrame(expectedVisibilityToken = null) {
&& !element.checkVisibility({ checkOpacity: true, checkVisibilityCSS: true })) {
return false;
}
return rect.bottom > 0
&& rect.right > 0
&& rect.top < view.innerHeight
&& rect.left < view.innerWidth;
const layoutWidth = Math.max(view.innerWidth, element.ownerDocument?.documentElement?.scrollWidth || 0);
const layoutHeight = Math.max(view.innerHeight, element.ownerDocument?.documentElement?.scrollHeight || 0);
const scrollX = Number(view.scrollX) || 0;
const scrollY = Number(view.scrollY) || 0;
return rect.bottom + scrollY > 0
&& rect.right + scrollX > 0
&& rect.top + scrollY < layoutHeight
&& rect.left + scrollX < layoutWidth;
};
const collectVideos = (doc, depth = 0, ancestorVisible = true, videos = [], seen = new Set()) => {
@@ -252,15 +256,19 @@ export function dispatchParentFrameVisibilityProbe(token) {
const rect = frame.getBoundingClientRect();
const style = window.getComputedStyle(frame);
const area = Math.max(0, rect.width) * Math.max(0, rect.height);
const intersectsViewport = rect.bottom > 0
&& rect.right > 0
&& rect.top < window.innerHeight
&& rect.left < window.innerWidth;
const layoutWidth = Math.max(window.innerWidth, document.documentElement?.scrollWidth || 0);
const layoutHeight = Math.max(window.innerHeight, document.documentElement?.scrollHeight || 0);
const scrollX = Number(window.scrollX) || 0;
const scrollY = Number(window.scrollY) || 0;
const intersectsLayout = rect.bottom + scrollY > 0
&& rect.right + scrollX > 0
&& rect.top + scrollY < layoutHeight
&& rect.left + scrollX < layoutWidth;
const browserReportsVisible = typeof frame.checkVisibility === 'function'
? frame.checkVisibility({ checkOpacity: true, checkVisibilityCSS: true })
: true;
const directlyVisible = area > 0
&& intersectsViewport
&& intersectsLayout
&& browserReportsVisible
&& style.display !== 'none'
&& style.visibility !== 'hidden'