Revert "[eric] frontend: cap live webviews at 8, farthest-from-center non-agent cards park first so heavy pages degrade instead of OOM"

This reverts commit fb3e3e702a.
This commit is contained in:
ciregenz
2026-06-09 17:36:00 -07:00
parent 6481fd999d
commit 1815ab18ae
@@ -20,9 +20,6 @@ const SNAPSHOT_MAX_W = 1024;
// Below this on-screen width a live page is indistinguishable from its placeholder,
// so booted-parked cards on a zoomed-out canvas stay parked until zoomed into.
const RESUME_MIN_CARD_PX = 220;
// Hard ceiling on simultaneous live webviews; past it the farthest-from-center
// non-agent card gets parked, so heavy pages degrade gracefully instead of OOMing.
const MAX_LIVE_WEBVIEWS = 8;
interface Viewport {
panX: number;
@@ -100,48 +97,37 @@ export function useWebviewSuspend(
vpH: el ? el.clientHeight : 800,
};
const liveCount = Object.keys(browserCards).filter((id) => !suspended[id]).length;
let budget = MAX_LIVE_WEBVIEWS - liveCount;
const parked = Object.keys(suspended)
.map((id) => [id, browserCards[id]] as const)
.filter(([, card]) => !!card)
.sort((a, b) => distFromCenter(a[1], vpRef.current) - distFromCenter(b[1], vpRef.current));
for (const [id, card] of parked) {
if (agentNeedsLive(id, card)) {
dispatch(resumeBrowserCard(id));
budget--;
continue;
}
if (budget <= 0) continue;
for (const id of Object.keys(suspended)) {
const card = browserCards[id];
if (!card) continue;
const bigEnough = card.width * zoom >= RESUME_MIN_CARD_PX;
if (bigEnough && cardIntersectsViewport(card, vpRef.current, RESUME_MARGIN_PX)) {
if ((bigEnough && cardIntersectsViewport(card, vpRef.current, RESUME_MARGIN_PX)) || agentNeedsLive(id, card)) {
dispatch(resumeBrowserCard(id));
budget--;
}
}
const timer = setTimeout(async () => {
const isSuspended = (id: string) => !!store.getState().dashboardLayout.suspendedBrowserCards[id];
for (const [id, card] of Object.entries(browserCards)) {
if (isSuspended(id)) continue;
if (store.getState().dashboardLayout.suspendedBrowserCards[id]) continue;
if (cardIntersectsViewport(card, vpRef.current, SUSPEND_MARGIN_PX)) continue;
if (agentNeedsLive(id, card)) continue;
const dataUrl = await captureCard(id, card);
// The capture await yielded; conditions may have changed under us.
if (!dataUrl || cardIntersectsViewport(card, vpRef.current, SUSPEND_MARGIN_PX) || agentNeedsLive(id, card)) continue;
dispatch(suspendBrowserCard({ browserId: id, dataUrl }));
}
const countLive = () => Object.keys(browserCards).filter((id) => !isSuspended(id)).length;
if (countLive() > MAX_LIVE_WEBVIEWS) {
const candidates = Object.entries(browserCards)
.filter(([id, card]) => !isSuspended(id) && !agentNeedsLive(id, card))
.sort((a, b) => distFromCenter(b[1], vpRef.current) - distFromCenter(a[1], vpRef.current));
for (const [id, card] of candidates) {
if (countLive() <= MAX_LIVE_WEBVIEWS) break;
const dataUrl = await captureCard(id, card);
if (!dataUrl || agentNeedsLive(id, card)) continue;
const wv = getWebview(id, card.activeTabId);
if (!wv) continue;
try {
if (wv.isLoading()) continue;
const url = wv.getURL();
if (!url || url === 'about:blank') continue;
const image = await wv.capturePage();
if (image.isEmpty()) continue;
// The capture await yielded; conditions may have changed under us.
if (cardIntersectsViewport(card, vpRef.current, SUSPEND_MARGIN_PX)) continue;
if (agentNeedsLive(id, card)) continue;
const dataUrl = image.getSize().width > SNAPSHOT_MAX_W
? image.resize({ width: SNAPSHOT_MAX_W, quality: 'good' }).toDataURL()
: image.toDataURL();
dispatch(suspendBrowserCard({ browserId: id, dataUrl }));
} catch {
// capture failed mid-teardown or mid-navigation; card just stays live
}
}
}, SETTLE_MS);
@@ -149,28 +135,3 @@ export function useWebviewSuspend(
return () => clearTimeout(timer);
}, [browserCards, suspended, panX, panY, zoom, viewportRef, dispatch, resizeTick]);
}
function distFromCenter(card: BrowserCardPosition, vp: Viewport): number {
const cx = (-vp.panX + vp.vpW / 2) / vp.zoom;
const cy = (-vp.panY + vp.vpH / 2) / vp.zoom;
const dx = card.x + card.width / 2 - cx;
const dy = card.y + card.height / 2 - cy;
return dx * dx + dy * dy;
}
async function captureCard(id: string, card: BrowserCardPosition): Promise<string | null> {
const wv = getWebview(id, card.activeTabId);
if (!wv) return null;
try {
if (wv.isLoading()) return null;
const url = wv.getURL();
if (!url || url === 'about:blank') return null;
const image = await wv.capturePage();
if (image.isEmpty()) return null;
return image.getSize().width > SNAPSHOT_MAX_W
? image.resize({ width: SNAPSHOT_MAX_W, quality: 'good' }).toDataURL()
: image.toDataURL();
} catch {
return null;
}
}