mirror of
https://github.com/openswarm-ai/openswarm.git
synced 2026-08-17 18:25:42 +02:00
[eric] browser: the docked mini re-measures when its slot announces a remount, retiring a 150ms forever-poll of layout reads
This commit is contained in:
@@ -292,6 +292,10 @@ const AgentChat: React.FC<AgentChatProps> = ({ sessionId: sessionIdProp, onClose
|
||||
// The live overlay stamps data-mini-live; while it paints, the frozen-shot backdrop must not (the clamped overlay leaves margins where a misaligned second copy of the page peeked through).
|
||||
'&[data-mini-live="1"] img': { opacity: 0 },
|
||||
} as const;
|
||||
// The slot announces its own (re)mount so the docked mini re-measures exactly then, instead of polling rects on a timer (the windowed transcript remounts it with no resize/pan event firing).
|
||||
const announceBrowserSlot = useCallback((el: HTMLElement | null) => {
|
||||
if (el) window.dispatchEvent(new CustomEvent('openswarm:browser-slot-mounted', { detail: { id } }));
|
||||
}, [id]);
|
||||
// A live webview cannot be clipped by the scroller, so the OVERLAY only shows while fully in view; this frozen shot is what scrolls and clips underneath it, ChatGPT-style.
|
||||
const dockedShot = dockedSurfaceId ? getMinimizedShot(dockedSurfaceId) : undefined;
|
||||
const browserSlotBody = dockedShot ? (
|
||||
@@ -1937,7 +1941,7 @@ const AgentChat: React.FC<AgentChatProps> = ({ sessionId: sessionIdProp, onClose
|
||||
return (
|
||||
<React.Fragment key={`${item.id}-with-browser`}>
|
||||
{rendered}
|
||||
<Box data-browser-slot={id} sx={browserSlotSx}>{browserSlotBody}</Box>
|
||||
<Box data-browser-slot={id} ref={announceBrowserSlot} sx={browserSlotSx}>{browserSlotBody}</Box>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
@@ -2090,7 +2094,7 @@ const AgentChat: React.FC<AgentChatProps> = ({ sessionId: sessionIdProp, onClose
|
||||
)}
|
||||
{/* Fallback dock slot for a browser that docked before any browser tool row exists (or whose row was compacted away); once a row appears the slot anchors at it instead (see browserAnchorItemId). The real card overlays this rect geometrically, so the webview never remounts; the mini hides itself when its slot scrolls mostly out of view, since a live webview can't be clipped by the scroller. */}
|
||||
{hasDockedBrowser && !browserAnchorItemId && (
|
||||
<Box data-browser-slot={id} sx={browserSlotSx}>{browserSlotBody}</Box>
|
||||
<Box data-browser-slot={id} ref={announceBrowserSlot} sx={browserSlotSx}>{browserSlotBody}</Box>
|
||||
)}
|
||||
</Box>
|
||||
</Box>
|
||||
|
||||
@@ -310,18 +310,23 @@ const BrowserCard: React.FC<Props> = ({
|
||||
window.addEventListener('openswarm:canvas-pan-changed', measure);
|
||||
document.addEventListener('visibilitychange', measure);
|
||||
const timers = [60, 250, 700].map((ms) => window.setTimeout(measure, ms));
|
||||
// Self-heal: the slot lives in the WINDOWED transcript and remounts without firing any of the events above, which left the mini scaled against a stale rect (visibly overflowing its frame) until the next pan. 150ms bounds how long any staleness can survive.
|
||||
const heal = window.setInterval(measure, 150);
|
||||
// The slot lives in the WINDOWED transcript and remounts without firing any of the events
|
||||
// above; it announces itself on mount now, which retired a 150ms forever-poll that forced a
|
||||
// layout read ~7x/sec per docked mini even while nothing moved (measure once per real change).
|
||||
const onSlotMounted = (e: Event): void => {
|
||||
if ((e as CustomEvent).detail?.id === dockedTo) measure();
|
||||
};
|
||||
window.addEventListener('openswarm:browser-slot-mounted', onSlotMounted);
|
||||
return () => {
|
||||
ro.disconnect();
|
||||
mo.disconnect();
|
||||
window.removeEventListener('resize', measure);
|
||||
window.removeEventListener('openswarm:canvas-pan-changed', measure);
|
||||
document.removeEventListener('visibilitychange', measure);
|
||||
window.removeEventListener('openswarm:browser-slot-mounted', onSlotMounted);
|
||||
scrollHost?.removeEventListener('scroll', onScroll);
|
||||
if (scrollRaf) cancelAnimationFrame(scrollRaf);
|
||||
timers.forEach((tm) => window.clearTimeout(tm));
|
||||
window.clearInterval(heal);
|
||||
};
|
||||
// dockParentCard x/y/w/h are re-measure triggers: the slot's client rect moves with the chat card.
|
||||
}, [dockedTo, dockParentExpanded, dockParentTiled, dockParentCard?.x, dockParentCard?.y, dockParentCard?.width, dockParentCard?.height, getCanvasState, dockParentCard]);
|
||||
|
||||
Reference in New Issue
Block a user