diff --git a/src/app/tools/tankopedia/components/SkeletonTankCard.tsx b/src/app/tools/tankopedia/components/SkeletonTankCard.tsx index 5aaff521e..a955951fc 100644 --- a/src/app/tools/tankopedia/components/SkeletonTankCard.tsx +++ b/src/app/tools/tankopedia/components/SkeletonTankCard.tsx @@ -1,10 +1,25 @@ import { Flex, Skeleton } from '@radix-ui/themes'; +import { memo, useRef } from 'react'; +import { useIntersection } from '../../../../hooks/useIntersection'; -export function SkeletonTankCard() { - return ( - - - - - ); +interface SkeletonTankCardProps { + onIntersection?: () => void; } + +export const SkeletonTankCard = memo( + ({ onIntersection }: SkeletonTankCardProps) => { + const card = useRef(null); + + useIntersection(() => onIntersection?.(), card, { + disabled: onIntersection === undefined, + }); + + return ( + + + + + ); + }, + () => true, +); diff --git a/src/app/tools/tankopedia/components/TankSearch/index.tsx b/src/app/tools/tankopedia/components/TankSearch/index.tsx index 964d50c9a..5d14205be 100644 --- a/src/app/tools/tankopedia/components/TankSearch/index.tsx +++ b/src/app/tools/tankopedia/components/TankSearch/index.tsx @@ -1,7 +1,9 @@ +'use client'; + import { Callout, Flex, FlexProps, Link, Text } from '@radix-ui/themes'; import { go } from 'fuzzysort'; import { times } from 'lodash'; -import { memo, use, useMemo } from 'react'; +import { memo, use, useEffect, useMemo, useState } from 'react'; import { AdMidSectionResponsive } from '../../../../../components/AdMidSectionResponsive'; import { ExperimentIcon } from '../../../../../components/ExperimentIcon'; import { TANK_CLASSES } from '../../../../../components/Tanks/components/Item/constants'; @@ -40,6 +42,9 @@ type TankSearchProps = Omit & { onSelectAll?: (tanks: TankDefinition[]) => void; }; +const PREVIEW_COUNT = 25; +const DEFAULT_LOADED_CARDS = 75; + export const TankSearch = memo( ({ compact, onSelect, onSelectAll, ...props }) => { const exempt = useAdExempt(); @@ -50,7 +55,7 @@ export const TankSearch = memo( const awaitedTankNames = use(tankNames); const filters = TankFilters.use(); const sort = TankopediaSort.use(); - const tanks = useMemo(() => { + const tanksFiltered = useMemo(() => { if (filters.search === undefined) { const filtered = awaitedTanksDefinitionsArray.filter((tank) => filterTank(filters, tank), @@ -379,6 +384,12 @@ export const TankSearch = memo( return searchedTanks; } }, [filters]); + const [loadedRows, setLoadedRows] = useState(DEFAULT_LOADED_CARDS); + const tanks = tanksFiltered.slice(0, loadedRows); + + useEffect(() => { + setLoadedRows(DEFAULT_LOADED_CARDS); + }, [filters, sort]); return ( @@ -447,6 +458,22 @@ export const TankSearch = memo( )} ))} + + {times( + Math.min(PREVIEW_COUNT, tanksFiltered.length - loadedRows), + (index) => { + return ( + { + setLoadedRows((state) => + Math.min(state + 2, tanksFiltered.length), + ); + }} + /> + ); + }, + )} )} diff --git a/src/app/tools/tankopedia/page.tsx b/src/app/tools/tankopedia/page.tsx index 827fa169a..92158b251 100644 --- a/src/app/tools/tankopedia/page.tsx +++ b/src/app/tools/tankopedia/page.tsx @@ -1,19 +1,12 @@ -'use client'; - -import { AdMidSectionResponsive } from '../../../components/AdMidSectionResponsive'; import PageWrapper from '../../../components/PageWrapper'; -import { useAdExempt } from '../../../hooks/useAdExempt'; import * as TankFilters from '../../../stores/tankFilters'; import { TankSearch } from './components/TankSearch'; export default function Page() { - const exempt = useAdExempt(); - return ( - {!exempt && } );