2022-03-07 13:11:28 +01:00
|
|
|
// @flow
|
|
|
|
import React from 'react';
|
|
|
|
import type { Node } from 'react';
|
|
|
|
|
|
|
|
type InjectedItem = { node: Node, index?: number, replace?: boolean };
|
|
|
|
|
2022-03-08 16:40:01 +01:00
|
|
|
/**
|
|
|
|
* Returns the index indicating where in the claim-grid to inject the ad element
|
|
|
|
* @param injectedItem
|
|
|
|
* @param listRef - A reference to the claim-grid
|
|
|
|
* @returns {number}
|
|
|
|
*/
|
2022-03-07 13:11:28 +01:00
|
|
|
export default function useLastVisibleItem(injectedItem: ?InjectedItem, listRef: any) {
|
|
|
|
const [injectedIndex, setInjectedIndex] = React.useState(injectedItem?.index);
|
|
|
|
|
|
|
|
React.useEffect(() => {
|
|
|
|
// Move to default injection index (last visible item)
|
|
|
|
if (injectedItem && injectedItem.index === undefined) {
|
|
|
|
// AD_INJECTION_DELAY_MS = average total-blocking-time incurred for
|
|
|
|
// loading ads. Delay to let higher priority tasks run first. Ideally,
|
|
|
|
// should use 'requestIdleCallback/requestAnimationFrame'.
|
|
|
|
const AD_INJECTION_DELAY_MS = 1500;
|
|
|
|
|
|
|
|
const timer = setTimeout(() => {
|
|
|
|
if (listRef.current) {
|
|
|
|
const screenBottom = window.innerHeight;
|
2022-03-08 16:40:01 +01:00
|
|
|
|
|
|
|
// claim preview tiles
|
2022-03-07 13:11:28 +01:00
|
|
|
const items = listRef.current.children;
|
|
|
|
|
2022-03-08 16:40:01 +01:00
|
|
|
// algo to return index of item, where ad will be injected before it
|
2022-03-07 13:11:28 +01:00
|
|
|
if (items.length) {
|
|
|
|
let i = 2; // Start from 2, so that the min possible is index-1
|
|
|
|
for (; i < items.length; ++i) {
|
|
|
|
const rect = items[i].getBoundingClientRect();
|
|
|
|
if (rect.top > screenBottom || rect.bottom > screenBottom) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
setInjectedIndex(i - 1);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fallback to index-1 (2nd item) for failures. No retries.
|
|
|
|
setInjectedIndex(1);
|
|
|
|
}, AD_INJECTION_DELAY_MS);
|
|
|
|
|
|
|
|
return () => clearTimeout(timer);
|
|
|
|
}
|
|
|
|
}, []);
|
|
|
|
|
|
|
|
return injectedIndex;
|
|
|
|
}
|