Skip to content

Commit 195467e

Browse files
authored
Merge 183f863 into b51367f
2 parents b51367f + 183f863 commit 195467e

File tree

4 files changed

+54
-11
lines changed

4 files changed

+54
-11
lines changed

special-pages/pages/new-tab/app/favorites/components/Favorites.js

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -257,8 +257,9 @@ function useVisibleRows(rows, rowHeight, safeAreaRef, expansion) {
257257
/**
258258
* decide which the start/end indexes should be, based on scroll position.
259259
* NOTE: this is called on scroll, so must not incur expensive checks/measurements - math only!
260+
* @param {number} rowCount - the number of rows in the dataset
260261
*/
261-
function setVisibleRowsForOffset() {
262+
function setVisibleRowsForOffset(rowCount) {
262263
if (!safeAreaRef.current) return console.warn('cannot access ref');
263264
const scrollY = mainScrollerRef.current?.scrollTop ?? 0;
264265
const offset = gridOffsetRef.current;
@@ -270,7 +271,7 @@ function useVisibleRows(rows, rowHeight, safeAreaRef, expansion) {
270271
start = scrollY - offset;
271272
}
272273
const startIndex = Math.floor(start / rowHeight);
273-
const endIndex = Math.min(Math.ceil(end / rowHeight), rows.length);
274+
const endIndex = Math.min(Math.ceil(end / rowHeight), rowCount);
274275

275276
// don't set state if the offset didn't change
276277
setVisibleRange((prev) => {
@@ -293,12 +294,18 @@ function useVisibleRows(rows, rowHeight, safeAreaRef, expansion) {
293294
updateGlobals();
294295

295296
// and set visible rows once the size is known
296-
setVisibleRowsForOffset();
297+
setVisibleRowsForOffset(rows.length);
297298

298299
const controller = new AbortController();
299300

300301
// when the main area is scrolled, update the visible offset for the rows.
301-
mainScrollerRef.current?.addEventListener('scroll', setVisibleRowsForOffset, { signal: controller.signal });
302+
mainScrollerRef.current?.addEventListener(
303+
'scroll',
304+
() => {
305+
setVisibleRowsForOffset(rows.length);
306+
},
307+
{ signal: controller.signal },
308+
);
302309

303310
return () => {
304311
controller.abort();
@@ -311,13 +318,13 @@ function useVisibleRows(rows, rowHeight, safeAreaRef, expansion) {
311318
if (lastWindowHeight === window.innerHeight) return;
312319
lastWindowHeight = window.innerHeight;
313320
updateGlobals();
314-
setVisibleRowsForOffset();
321+
setVisibleRowsForOffset(rows.length);
315322
}
316323
window.addEventListener('resize', handler);
317324
return () => {
318325
return window.removeEventListener('resize', handler);
319326
};
320-
}, []);
327+
}, [rows.length]);
321328

322329
useEffect(() => {
323330
if (!contentTubeRef.current) return console.warn('cannot find content tube');
@@ -331,7 +338,7 @@ function useVisibleRows(rows, rowHeight, safeAreaRef, expansion) {
331338
clearTimeout(debounceTimer);
332339
debounceTimer = setTimeout(() => {
333340
updateGlobals();
334-
setVisibleRowsForOffset();
341+
setVisibleRowsForOffset(rows.length);
335342
}, 50);
336343
}
337344
});
@@ -341,7 +348,7 @@ function useVisibleRows(rows, rowHeight, safeAreaRef, expansion) {
341348
resizer.disconnect();
342349
clearTimeout(debounceTimer);
343350
};
344-
}, []);
351+
}, [rows.length]);
345352

346353
return { start, end };
347354
}

special-pages/pages/new-tab/app/favorites/integration-tests/favorites.page.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,4 +339,20 @@ export class FavoritesPage {
339339
// verify the DOM is updated
340340
await expect(page.getByTestId('FavoritesConfigured').locator('a[href]')).toHaveCount(to);
341341
}
342+
343+
/**
344+
* Simulate getting entirely fresh data
345+
*/
346+
async receivesNewDataAndShowsAll(count) {
347+
const { page } = this.ntp;
348+
349+
const items = gen(count);
350+
await this.ntp.mocks.simulateSubscriptionMessage('favorites_onDataUpdate', items);
351+
352+
// The bug occurred after a debounced timer, so this timer reproduces it
353+
await page.waitForTimeout(100);
354+
355+
// Every tile should be shown
356+
await this.waitForNumFavorites(count);
357+
}
342358
}

special-pages/pages/new-tab/app/favorites/integration-tests/favorites.spec.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,4 +153,24 @@ test.describe('newtab favorites', () => {
153153
// assert there's still 16 showing
154154
await favorites.waitForNumFavorites(16);
155155
});
156+
test('accepts new data when already expanded', async ({ page }, workerInfo) => {
157+
const ntp = NewtabPage.create(page, workerInfo);
158+
await ntp.reducedMotion();
159+
160+
const favorites = new FavoritesPage(ntp);
161+
162+
// open the page with enough next-step + favorites for both to be expanded
163+
await ntp.openPage({
164+
favorites: '12',
165+
additional: {
166+
'favorites.config.expansion': 'expanded',
167+
},
168+
});
169+
170+
// control: ensure it's just the expected start amount
171+
await favorites.waitForNumFavorites(12);
172+
173+
// then, assert all further elements are shown
174+
await favorites.receivesNewDataAndShowsAll(26);
175+
});
156176
});

special-pages/pages/new-tab/app/mock-transport.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -466,10 +466,10 @@ export function mockTransport() {
466466
}
467467
case 'favorites_getConfig': {
468468
/** @type {FavoritesConfig} */
469-
const defaultConfig = { expansion: 'collapsed', animation: { kind: 'none' } };
469+
const defaultConfig = { expansion: 'collapsed', animation: { kind: 'view-transitions' } };
470470
const fromStorage = read('favorites_config') || defaultConfig;
471-
if (url.searchParams.get('favorites.animation') === 'view-transitions') {
472-
fromStorage.animation = { kind: 'view-transitions' };
471+
if (url.searchParams.get('favorites.config.expansion') === 'expanded') {
472+
defaultConfig.expansion = 'expanded';
473473
}
474474
return Promise.resolve(fromStorage);
475475
}

0 commit comments

Comments
 (0)