Generalize useGetLastVisibleSlot

It was meant to be general-purpose in the first-place, but ended being tied to ads due to time constraint and also bad documentation.

No functional change.
This commit is contained in:
infinite-persistence 2022-04-18 16:37:10 +08:00
parent f5a0f39f59
commit 0e233e04a8
No known key found for this signature in database
GPG key ID: B9C3252EDC3D0AA0
3 changed files with 20 additions and 28 deletions

View file

@ -106,7 +106,8 @@ export default function ClaimList(props: Props) {
// Resolve the index for injectedItem, if provided; else injectedIndex will be 'undefined'. // Resolve the index for injectedItem, if provided; else injectedIndex will be 'undefined'.
const listRef = React.useRef(); const listRef = React.useRef();
const injectedIndex = useGetLastVisibleSlot(injectedItem, listRef); const findLastVisibleSlot = injectedItem && injectedItem.node && injectedItem.index === undefined;
const lastVisibleIndex = useGetLastVisibleSlot(listRef, !findLastVisibleSlot);
// Exclude prefix uris in these results variables. We don't want to show // Exclude prefix uris in these results variables. We don't want to show
// anything if the search failed or timed out. // anything if the search failed or timed out.
@ -205,7 +206,7 @@ export default function ClaimList(props: Props) {
); );
const getInjectedItem = (index) => { const getInjectedItem = (index) => {
if (injectedItem && injectedItem.node && injectedIndex === index) { if (injectedItem && injectedItem.node && lastVisibleIndex === index) {
return injectedItem.node; return injectedItem.node;
} }
return null; return null;

View file

@ -93,7 +93,8 @@ function ClaimTilesDiscover(props: Props) {
} = props; } = props;
const listRef = React.useRef(); const listRef = React.useRef();
const injectedIndex = useGetLastVisibleSlot(injectedItem, listRef); const findLastVisibleSlot = injectedItem && injectedItem.node && injectedItem.index === undefined;
const lastVisibleIndex = useGetLastVisibleSlot(listRef, !findLastVisibleSlot);
const prevUris = React.useRef(); const prevUris = React.useRef();
const claimSearchUris = claimSearchResults || []; const claimSearchUris = claimSearchResults || [];
@ -186,13 +187,13 @@ function ClaimTilesDiscover(props: Props) {
{finalUris && finalUris.length {finalUris && finalUris.length
? finalUris.map((uri, i) => { ? finalUris.map((uri, i) => {
if (uri) { if (uri) {
if (injectedIndex === i && injectedItem && injectedItem.replace) { if (lastVisibleIndex === i && injectedItem && injectedItem.replace) {
return <React.Fragment key={uri}>{injectedItem.node}</React.Fragment>; return <React.Fragment key={uri}>{injectedItem.node}</React.Fragment>;
} }
return ( return (
<React.Fragment key={uri}> <React.Fragment key={uri}>
{injectedIndex === i && injectedItem && injectedItem.node} {lastVisibleIndex === i && injectedItem && injectedItem.node}
<ClaimPreviewTile <ClaimPreviewTile
showNoSourceClaims={hasNoSource || showNoSourceClaims} showNoSourceClaims={hasNoSource || showNoSourceClaims}
uri={uri} uri={uri}

View file

@ -1,34 +1,24 @@
// @flow // @flow
import React from 'react'; 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 * Returns the last visible slot in a list.
* @param injectedItem *
* @param listRef - A reference to the claim-grid * @param listRef A reference to the list.
* @returns {number} * @param skipEval Skip the evaluation/effect. Useful if the client knows the effect is not needed in certain scenarios.
* @param checkDelayMs Delay before running the effect. Useful if the list is known to not be populated until later.
* @returns {number | undefined} Zero-indexed number representing the last visible slot.
*/ */
export default function useGetLastVisibleSlot(injectedItem: ?InjectedItem, listRef: any) { export default function useGetLastVisibleSlot(listRef: any, skipEval: boolean, checkDelayMs: number = 1500) {
const [injectedIndex, setInjectedIndex] = React.useState(injectedItem?.index); const [lastVisibleIndex, setLastVisibleIndex] = React.useState(undefined);
React.useEffect(() => { React.useEffect(() => {
// Move to default injection index (last visible item) if (!skipEval) {
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(() => { const timer = setTimeout(() => {
if (listRef.current) { if (listRef.current) {
const screenBottom = window.innerHeight; const screenBottom = window.innerHeight;
// claim preview tiles
const items = listRef.current.children; const items = listRef.current.children;
// algo to return index of item, where ad will be injected before it
if (items.length) { if (items.length) {
let i = 2; // Start from 2, so that the min possible is index-1 let i = 2; // Start from 2, so that the min possible is index-1
for (; i < items.length; ++i) { for (; i < items.length; ++i) {
@ -38,18 +28,18 @@ export default function useGetLastVisibleSlot(injectedItem: ?InjectedItem, listR
} }
} }
setInjectedIndex(i - 1); setLastVisibleIndex(i - 1);
return; return;
} }
} }
// Fallback to index-1 (2nd item) for failures. No retries. // Fallback to index-1 (2nd item) for failures. No retries.
setInjectedIndex(1); setLastVisibleIndex(1);
}, AD_INJECTION_DELAY_MS); }, checkDelayMs);
return () => clearTimeout(timer); return () => clearTimeout(timer);
} }
}, []); }, []);
return injectedIndex; return lastVisibleIndex;
} }