fix(workspace): defer observed gallery layout writes (#207)

This commit is contained in:
Vito Sansevero
2026-10-17 13:30:46 -07:00
parent 4e309ee91a
commit 9fe63ab516
2 changed files with 33 additions and 2 deletions
+21
View File
@@ -172,3 +172,24 @@ test('filtering away a selected image aborts its pending metadata request',async
await expect.poll(()=>page.evaluate(()=>window.inspectionAborts),{timeout:1500}).toBeGreaterThan(baseline);
} finally {release();}
});
test('responsive gallery defers observed size writes and still fits the new viewport',async({page})=>{
await page.addInitScript(()=>{
const Native=window.ResizeObserver;window.inlineResizeWrites=0;
window.ResizeObserver=class extends Native {
constructor(callback){super((entries,observer)=>{
const sizes=entries.map(entry=>entry.target.style.height);
callback(entries,observer);
entries.forEach((entry,index)=>{
if(entry.target.classList.contains('image-grid')&&entry.target.style.height!==sizes[index])window.inlineResizeWrites++;
});
});}
};
});
await page.setViewportSize({width:1280,height:900});await page.goto(workspace);
await expect(page.locator('.image-card')).toHaveCount(4);
await page.setViewportSize({width:390,height:844});
await expect.poll(()=>page.locator('.image-card').first().evaluate(node=>node.getBoundingClientRect().width)).toBeLessThan(390);
await expect.poll(()=>page.locator('.image-grid').evaluate(node=>Number.parseFloat(node.style.height))).toBeGreaterThan(900);
expect(await page.evaluate(()=>window.inlineResizeWrites)).toBe(0);
});
+12 -2
View File
@@ -287,9 +287,19 @@ export function mountImages(main, api, parentScope) {
grid.style.height = `${geometry.height}px`;
renderVisible();
}
const resize = new ResizeObserver(updateLayout); resize.observe(grid);
let resizeFrame = 0, observedWidth;
const resize = new ResizeObserver(entries => {
const width = entries[0].contentRect.width;
if (width === observedWidth) return;
observedWidth = width;
if (!resizeFrame) resizeFrame = requestAnimationFrame(() => {
resizeFrame = 0;
updateLayout();
});
});
resize.observe(grid);
scope.listen(window, 'scroll', scheduleVisible);
scope.cleanup(() => { resize.disconnect(); observer?.disconnect(); cancelAnimationFrame(frame); cancelAnimationFrame(loadFrame); });
scope.cleanup(() => { resize.disconnect(); observer?.disconnect(); cancelAnimationFrame(resizeFrame); cancelAnimationFrame(frame); cancelAnimationFrame(loadFrame); });
function renderState(next) {
const changed = state?.items !== next.items;
if (changed) {