From aae70d442d0d94f3ca6b995318770400f3f3fa1e Mon Sep 17 00:00:00 2001 From: thePR0M3TH3AN <53631862+PR0M3TH3AN@users.noreply.github.com> Date: Fri, 17 Oct 2025 13:33:06 -0400 Subject: [PATCH] Improve blog embed resize coordination --- js/blog/index.js | 62 +++++++++++++++++++++++++++++++++++++++--------- views/blog.html | 62 +++++++++++++++++++++++------------------------- 2 files changed, 81 insertions(+), 43 deletions(-) diff --git a/js/blog/index.js b/js/blog/index.js index 73cd5741..5618223b 100644 --- a/js/blog/index.js +++ b/js/blog/index.js @@ -133,7 +133,12 @@ function resolveNotes() { } function setupEmbedHeightBroadcast({ root, registerCleanup }) { - if (typeof window === 'undefined' || !root || window.parent === window) { + if (typeof window === 'undefined' || window.parent === window) { + return; + } + + const element = root || document.querySelector('.blog-app-root'); + if (!element) { return; } @@ -149,11 +154,12 @@ function setupEmbedHeightBroadcast({ root, registerCleanup }) { })(); let lastHeight = null; + let pendingFrame = null; - const postHeight = (force = false) => { - const rect = root.getBoundingClientRect(); - const height = Math.ceil(rect.height); - if (!Number.isFinite(height) || height < 0) { + const measureAndPost = (force = false) => { + const rect = element.getBoundingClientRect(); + const height = Math.max(0, Math.ceil(rect.height)); + if (!Number.isFinite(height)) { return; } if (!force && height === lastHeight) { @@ -167,21 +173,47 @@ function setupEmbedHeightBroadcast({ root, registerCleanup }) { } }; - const rafId = window.requestAnimationFrame(() => { - postHeight(true); + const queueMeasurement = (force = false) => { + if (force) { + measureAndPost(true); + return; + } + if (pendingFrame != null) { + return; + } + pendingFrame = window.requestAnimationFrame(() => { + pendingFrame = null; + measureAndPost(false); + }); + }; + + pendingFrame = window.requestAnimationFrame(() => { + pendingFrame = null; + measureAndPost(true); }); + registerCleanup(() => { - window.cancelAnimationFrame(rafId); + if (pendingFrame != null) { + window.cancelAnimationFrame(pendingFrame); + pendingFrame = null; + } }); if (typeof ResizeObserver === 'function') { const observer = new ResizeObserver(() => { - postHeight(); + queueMeasurement(); }); - observer.observe(root); + observer.observe(element); registerCleanup(() => { observer.disconnect(); }); + } else { + const intervalId = window.setInterval(() => { + queueMeasurement(); + }, 500); + registerCleanup(() => { + window.clearInterval(intervalId); + }); } const handleMessage = (event) => { @@ -192,7 +224,7 @@ function setupEmbedHeightBroadcast({ root, registerCleanup }) { return; } if (event?.data?.type === 'bitvid-blog-request-height') { - postHeight(true); + queueMeasurement(true); } }; @@ -200,6 +232,14 @@ function setupEmbedHeightBroadcast({ root, registerCleanup }) { registerCleanup(() => { window.removeEventListener('message', handleMessage); }); + + const handleLoad = () => { + queueMeasurement(true); + }; + window.addEventListener('load', handleLoad, { once: true }); + registerCleanup(() => { + window.removeEventListener('load', handleLoad); + }); } function formatDate(unixSeconds, { includeTime = false } = {}) { diff --git a/views/blog.html b/views/blog.html index 74f94a99..0d5448db 100644 --- a/views/blog.html +++ b/views/blog.html @@ -35,8 +35,29 @@ iframe.style.removeProperty('max-height'); }; - let stopRetryLoop = () => {}; let receivedFirstHeight = false; + let retryIntervalId = null; + + const stopRequestLoop = () => { + if (retryIntervalId === null) { + return; + } + window.clearInterval(retryIntervalId); + retryIntervalId = null; + }; + + const startRequestLoop = () => { + if (retryIntervalId !== null) { + return; + } + retryIntervalId = window.setInterval(() => { + if (receivedFirstHeight || signal.aborted) { + stopRequestLoop(); + return; + } + requestHeight(); + }, 250); + }; const handleMessage = (event) => { if (event.source !== iframe.contentWindow) { @@ -48,7 +69,7 @@ if (event.data?.type === 'bitvid-blog-resize') { applyHeight(event.data.height); receivedFirstHeight = true; - stopRetryLoop(); + stopRequestLoop(); } }; @@ -64,35 +85,6 @@ ); }; - const startRetryLoop = () => { - const maxAttempts = 5; - let attempts = 0; - const retryIntervalMs = 200; - const intervalId = window.setInterval(() => { - attempts += 1; - if (attempts > maxAttempts || receivedFirstHeight) { - window.clearInterval(intervalId); - return; - } - requestHeight(); - }, retryIntervalMs); - - const stop = () => { - window.clearInterval(intervalId); - }; - - if (signal.aborted) { - stop(); - } else { - signal.addEventListener('abort', stop, { once: true }); - } - - stopRetryLoop = () => { - stop(); - stopRetryLoop = () => {}; - }; - }; - let hasStarted = false; const runInitialRequests = () => { @@ -101,7 +93,12 @@ } hasStarted = true; requestHeight(); - startRetryLoop(); + startRequestLoop(); + if (signal.aborted) { + stopRequestLoop(); + } else { + signal.addEventListener('abort', stopRequestLoop, { once: true }); + } }; iframe.addEventListener('load', () => { @@ -119,6 +116,7 @@ window.addEventListener('pagehide', () => { abortController.abort(); + stopRequestLoop(); }, { once: true }); }