lbry-desktop/ui/effects/use-last-visible-item.js
2022-03-08 10:53:52 -05:00

55 lines
1.8 KiB
JavaScript

// @flow
import React from 'react';
import type { Node } from 'react';
type InjectedItem = { node: Node, index?: number, replace?: boolean };
/**
* 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}
*/
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;
// claim preview tiles
const items = listRef.current.children;
// algo to return index of item, where ad will be injected before it
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;
}