diff --git a/src/app/Components/ArtworkGrids/ArtworkGridItem.tsx b/src/app/Components/ArtworkGrids/ArtworkGridItem.tsx index efa4f65ac42..d452e6a1617 100644 --- a/src/app/Components/ArtworkGrids/ArtworkGridItem.tsx +++ b/src/app/Components/ArtworkGrids/ArtworkGridItem.tsx @@ -32,6 +32,7 @@ import { ArtworkItemCTAs } from "app/Scenes/Artwork/Components/ArtworkItemCTAs" import { useGetNewSaveAndFollowOnArtworkCardExperimentVariant } from "app/Scenes/Artwork/utils/useGetNewSaveAndFollowOnArtworkCardExperimentVariant" import { GlobalStore } from "app/store/GlobalStore" import { navigate } from "app/system/navigation/navigate" +import { ElementInView } from "app/utils/ElementInView" import { useArtworkBidding } from "app/utils/Websockets/auctions/useArtworkBidding" import { getArtworkSignalTrackingFields } from "app/utils/getArtworkSignalTrackingFields" import { saleMessageOrBidInfo } from "app/utils/getSaleMessgeOrBidInfo" @@ -40,6 +41,7 @@ import { useFeatureFlag } from "app/utils/hooks/useFeatureFlag" import { NUM_COLUMNS_MASONRY } from "app/utils/masonryHelpers" import { useSaveArtwork } from "app/utils/mutations/useSaveArtwork" import { RandomNumberGenerator } from "app/utils/placeholders" +import { usePrefetch } from "app/utils/queryPrefetching" import { ArtworkActionTrackingProps, tracks as artworkActionTracks, @@ -124,6 +126,7 @@ export const Artwork: React.FC = ({ }) => { const itemRef = useRef() const color = useColor() + const prefetchUrl = usePrefetch() const tracking = useTracking() const [showCreateArtworkAlertModal, setShowCreateArtworkAlertModal] = useState(false) const showBlurhash = useFeatureFlag("ARShowBlurhashImagePlaceholder") @@ -131,6 +134,7 @@ export const Artwork: React.FC = ({ const enableNewSaveAndFollowOnArtworkCard = useFeatureFlag( "AREnableNewSaveAndFollowOnArtworkCard" ) + const enableViewPortPrefetching = useFeatureFlag("AREnableViewPortPrefetching") const { enabled, @@ -284,192 +288,200 @@ export const Artwork: React.FC = ({ await item._disappearable?.disappear() } + const handleVisible = () => { + if (enableViewPortPrefetching && artwork.href) { + prefetchUrl(artwork.href) + } + } + const displayArtworkSocialSignal = !isAuction && !displayLimitedTimeOfferSignal && !!collectorSignals return ( - ((artwork as any)._disappearable = ref)}> - handleSupress(artwork as any)} - contextModule={contextModule} - contextScreenOwnerType={contextScreenOwnerType} - onCreateAlertActionPress={() => setShowCreateArtworkAlertModal(true)} - artwork={artwork} - hideCreateAlertOnArtworkPreview={hideCreateAlertOnArtworkPreview} - > - + ((artwork as any)._disappearable = ref)}> + handleSupress(artwork as any)} + contextModule={contextModule} + contextScreenOwnerType={contextScreenOwnerType} + onCreateAlertActionPress={() => setShowCreateArtworkAlertModal(true)} + artwork={artwork} + hideCreateAlertOnArtworkPreview={hideCreateAlertOnArtworkPreview} > - - {!!artwork.image?.url && ( - - - - )} - {!!canShowAuctionProgressBar && ( - - - + + {!!artwork.image?.url && ( + + - - - )} - - + + )} + {!!canShowAuctionProgressBar && ( + + + + + + )} + - {!!showLotLabel && !!artwork.saleArtwork?.lotLabel && ( - - Lot {artwork.saleArtwork.lotLabel} - - )} - {!!artwork.artistNames && ( - - {artwork.artistNames} - - )} - {!!artwork.title && ( - - - {artwork.title} + + {!!showLotLabel && !!artwork.saleArtwork?.lotLabel && ( + + Lot {artwork.saleArtwork.lotLabel} - {artwork.date ? `, ${artwork.date}` : ""} - - )} - {!hidePartner && !!artwork.partner?.name && ( - - {artwork.partner.name} - - )} - {!!displayPriceOfferMessage && ( - - - {priceOfferMessage.priceWithDiscountMessage} + )} + {!!artwork.artistNames && ( + + {artwork.artistNames} - - {" "} - (List price: {priceOfferMessage.priceListedMessage}) + )} + {!!artwork.title && ( + + + {artwork.title} + + {artwork.date ? `, ${artwork.date}` : ""} - - )} - {!!saleInfo && !hideSaleInfo && !displayPriceOfferMessage && ( - - )} - - {!!artwork.isUnlisted && ( - - Exclusive Access - - )} + )} + {!hidePartner && !!artwork.partner?.name && ( + + {artwork.partner.name} + + )} + {!!displayPriceOfferMessage && ( + + + {priceOfferMessage.priceWithDiscountMessage} + + + {" "} + (List price: {priceOfferMessage.priceListedMessage}) + + + )} + {!!saleInfo && !hideSaleInfo && !displayPriceOfferMessage && ( + + )} - {!!isAuction && !!collectorSignals && ( - - )} + {!!artwork.isUnlisted && ( + + Exclusive Access + + )} - {!!displayArtworkSocialSignal && ( - - )} - + {!!isAuction && !!collectorSignals && ( + + )} - {!!showOldSaveCTA && ( - - {!!isAuction && !!collectorSignals?.auction?.lotWatcherCount && ( - - {collectorSignals.auction.lotWatcherCount} - + {!!displayArtworkSocialSignal && ( + )} - - - - )} - {!!enableNewSaveAndFollowOnArtworkCard && - !!(enableNewSaveCTA || enableNewSaveAndFollowCTAs) && ( - + {!!showOldSaveCTA && ( + + {!!isAuction && !!collectorSignals?.auction?.lotWatcherCount && ( + + {collectorSignals.auction.lotWatcherCount} + + )} + + + + )} - - - - - - - setShowCreateArtworkAlertModal(false)} - visible={showCreateArtworkAlertModal} - /> - + {!!enableNewSaveAndFollowOnArtworkCard && + !!(enableNewSaveCTA || enableNewSaveAndFollowCTAs) && ( + + )} + + + + + + + + setShowCreateArtworkAlertModal(false)} + visible={showCreateArtworkAlertModal} + /> + + ) } diff --git a/src/app/store/config/features.ts b/src/app/store/config/features.ts index ac7aa8ba696..0e098d53622 100644 --- a/src/app/store/config/features.ts +++ b/src/app/store/config/features.ts @@ -265,6 +265,12 @@ export const features = { readyForRelease: false, showInDevMenu: true, }, + AREnableViewPortPrefetching: { + description: "Enable viewport prefetching", + readyForRelease: true, + showInDevMenu: true, + echoFlagKey: "AREnableViewPortPrefetching", + }, } satisfies { [key: string]: FeatureDescriptor } export interface DevToggleDescriptor { diff --git a/src/app/utils/queryPrefetching.ts b/src/app/utils/queryPrefetching.ts index fcdc519668f..7264ee8c895 100644 --- a/src/app/utils/queryPrefetching.ts +++ b/src/app/utils/queryPrefetching.ts @@ -17,9 +17,11 @@ export const usePrefetch = () => { } const prefetchRoute = async ( - route: string, + route?: string | null, variables?: VariablesOf ) => { + if (!route) return null + if (await isRateLimited()) { if (logPrefetching) console.log("[queryPrefetching] Rate limit reached.") return