Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: extract non cacheable fields out of grid items #11093

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 17 additions & 68 deletions src/app/Components/ArtworkGrids/ArtworkGridItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ import { ActionType, ContextModule, OwnerType, TappedMainArtworkGrid } from "@ar
import {
Box,
Flex,
HeartFillIcon,
HeartIcon,
Image,
Skeleton,
SkeletonBox,
Expand All @@ -19,31 +17,26 @@ import { CreateArtworkAlertModal } from "app/Components/Artist/ArtistArtworks/Cr
import { filterArtworksParams } from "app/Components/ArtworkFilter/ArtworkFilterHelpers"
import { ArtworksFiltersStore } from "app/Components/ArtworkFilter/ArtworkFilterStore"
import { ArtworkAuctionTimer } from "app/Components/ArtworkGrids/ArtworkAuctionTimer"
import { ArtworkGridItemSaveButtonQueryRenderer } from "app/Components/ArtworkGrids/ArtworkGridItemSaveButton"
import { ArtworkSocialSignal } from "app/Components/ArtworkGrids/ArtworkSocialSignal"
import { useSaveArtworkToArtworkLists } from "app/Components/ArtworkLists/useSaveArtworkToArtworkLists"
import { ArtworkSaleMessage } from "app/Components/ArtworkRail/ArtworkSaleMessage"
import { ContextMenuArtwork } from "app/Components/ContextMenu/ContextMenuArtwork"
import { DurationProvider } from "app/Components/Countdown"
import { Disappearable, DissapearableArtwork } from "app/Components/Disappearable"
import { ProgressiveOnboardingSaveArtwork } from "app/Components/ProgressiveOnboarding/ProgressiveOnboardingSaveArtwork"
import { HEART_ICON_SIZE } from "app/Components/constants"
import { PartnerOffer } from "app/Scenes/Activity/components/PartnerOfferCreatedNotification"
import { ArtworkItemCTAs } from "app/Scenes/Artwork/Components/ArtworkItemCTAs"
import { getNewSaveAndFollowOnArtworkCardExperimentVariant } from "app/Scenes/Artwork/utils/getNewSaveAndFollowOnArtworkCardExperimentVariant"
import { GlobalStore } from "app/store/GlobalStore"
import { navigate } from "app/system/navigation/navigate"
import { useArtworkBidding } from "app/utils/Websockets/auctions/useArtworkBidding"
import { useExperimentVariant } from "app/utils/experiments/hooks"
import { useArtworkNonCacheableFields } from "app/utils/fetchArtworkNonCacheableFields"
import { getArtworkSignalTrackingFields } from "app/utils/getArtworkSignalTrackingFields"
import { saleMessageOrBidInfo } from "app/utils/getSaleMessgeOrBidInfo"
import { getTimer } from "app/utils/getTimer"
import { useFeatureFlag } from "app/utils/hooks/useFeatureFlag"
import { useSaveArtwork } from "app/utils/mutations/useSaveArtwork"
import { RandomNumberGenerator } from "app/utils/placeholders"
import {
ArtworkActionTrackingProps,
tracks as artworkActionTracks,
} from "app/utils/track/ArtworkActions"
import { ArtworkActionTrackingProps } from "app/utils/track/ArtworkActions"
import React, { useRef, useState } from "react"
import { View, ViewProps } from "react-native"
import { createFragmentContainer, graphql } from "react-relay"
Expand Down Expand Up @@ -129,6 +122,10 @@ export const Artwork: React.FC<ArtworkProps> = ({
"onyx_artwork-card-save-and-follow-cta-redesign"
)

const nonCacheableData = useArtworkNonCacheableFields(artwork.internalID)

console.log({ isSavedNonCacheable: nonCacheableData?.artwork?.isSaved })

const { enableShowOldSaveCTA, enableNewSaveCTA, enableNewSaveAndFollowCTAs } =
getNewSaveAndFollowOnArtworkCardExperimentVariant(
newSaveAndFollowOnArtworkCardExperiment.enabled,
Expand Down Expand Up @@ -179,35 +176,6 @@ export const Artwork: React.FC<ArtworkProps> = ({
}
}

const onArtworkSavedOrUnSaved = (saved: boolean) => {
const { availability, isAcquireable, isBiddable, isInquireable, isOfferable } = artwork
const params = {
acquireable: isAcquireable,
availability,
biddable: isBiddable,
context_module: contextModule,
context_screen: contextScreen,
context_screen_owner_id: contextScreenOwnerId,
context_screen_owner_slug: contextScreenOwnerSlug,
context_screen_owner_type: contextScreenOwnerType,
inquireable: isInquireable,
offerable: isOfferable,
}
tracking.trackEvent(artworkActionTracks.saveOrUnsaveArtwork(saved, params))
}

const { isSaved, saveArtworkToLists } = useSaveArtworkToArtworkLists({
artworkFragmentRef: artwork,
onCompleted: onArtworkSavedOrUnSaved,
})

const handleArtworkSave = useSaveArtwork({
id: artwork.id,
internalID: artwork.internalID,
isSaved: !!artwork.isSaved,
onCompleted: onArtworkSavedOrUnSaved,
})

const { hasEnded } = getTimer(partnerOffer?.endAt || "")

const handleTap = () => {
Expand Down Expand Up @@ -425,13 +393,16 @@ export const Artwork: React.FC<ArtworkProps> = ({
{collectorSignals.auction.lotWatcherCount}
</Text>
)}
<Touchable
haptic
onPress={disableArtworksListPrompt ? handleArtworkSave : saveArtworkToLists}
testID="save-artwork-icon"
>
<ArtworkHeartIcon isSaved={!!isSaved} index={itemIndex} />
</Touchable>
<ArtworkGridItemSaveButtonQueryRenderer
disableArtworksListPrompt={disableArtworksListPrompt}
id={artwork.internalID}
contextModule={contextModule}
contextScreen={contextScreen}
contextScreenOwnerId={contextScreenOwnerId}
contextScreenOwnerSlug={contextScreenOwnerSlug}
contextScreenOwnerType={contextScreenOwnerType}
itemIndex={itemIndex}
/>
</Flex>
)}

Expand Down Expand Up @@ -463,26 +434,6 @@ export const Artwork: React.FC<ArtworkProps> = ({
)
}

const ArtworkHeartIcon: React.FC<{ isSaved: boolean | null; index?: number }> = ({
isSaved,
index,
}) => {
const iconProps = { height: HEART_ICON_SIZE, width: HEART_ICON_SIZE, testID: "empty-heart-icon" }

if (isSaved) {
return <HeartFillIcon {...iconProps} testID="filled-heart-icon" fill="blue100" />
}
if (index === 0) {
// We only try to show the save onboard Popover in the 1st element
return (
<ProgressiveOnboardingSaveArtwork>
<HeartIcon {...iconProps} />
</ProgressiveOnboardingSaveArtwork>
)
}
return <HeartIcon {...iconProps} />
}

export default createFragmentContainer(Artwork, {
artwork: graphql`
fragment ArtworkGridItem_artwork on Artwork
Expand Down Expand Up @@ -510,7 +461,6 @@ export default createFragmentContainer(Artwork, {
isBiddable
isInquireable
isOfferable
isSaved
isUnlisted
artistNames
href
Expand Down Expand Up @@ -571,7 +521,6 @@ export default createFragmentContainer(Artwork, {
...ArtworkSocialSignal_collectorSignals
}
...ArtworkSaleMessage_artwork
...useSaveArtworkToArtworkLists_artwork
}
`,
})
Expand Down
124 changes: 124 additions & 0 deletions src/app/Components/ArtworkGrids/ArtworkGridItemSaveButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import { Flex, HeartFillIcon, HeartIcon, Text, Touchable } from "@artsy/palette-mobile"
import {
ArtworkGridItemSaveButtonQuery,
ArtworkGridItemSaveButtonQuery$data,
} from "__generated__/ArtworkGridItemSaveButtonQuery.graphql"
import { useSaveArtworkToArtworkLists } from "app/Components/ArtworkLists/useSaveArtworkToArtworkLists"
import { ProgressiveOnboardingSaveArtwork } from "app/Components/ProgressiveOnboarding/ProgressiveOnboardingSaveArtwork"
import { HEART_ICON_SIZE } from "app/Components/constants"
import { NoFallback } from "app/utils/hooks/withSuspense"
import { useSaveArtwork } from "app/utils/mutations/useSaveArtwork"
import { ArtworkActionTrackingProps, tracks } from "app/utils/track/ArtworkActions"
import { Suspense } from "react"
import { graphql, useLazyLoadQuery } from "react-relay"
import { useTracking } from "react-tracking"

interface ArtworkGridItemSaveButtonProps extends ArtworkActionTrackingProps {
disableArtworksListPrompt: boolean
id: string
itemIndex?: number
}

export const ArtworkGridItemSaveButton = ({
contextModule,
contextScreen,
contextScreenOwnerId,
contextScreenOwnerSlug,
contextScreenOwnerType,
disableArtworksListPrompt,
id,
itemIndex,
}: ArtworkGridItemSaveButtonProps) => {
const { trackEvent } = useTracking()
const data = useLazyLoadQuery<ArtworkGridItemSaveButtonQuery>(
graphql`
query ArtworkGridItemSaveButtonQuery($id: String!) {
artwork(id: $id) {
id
internalID
isSaved
availability
isAcquireable
isBiddable
isInquireable
isOfferable
...useSaveArtworkToArtworkLists_artwork
}
}
`,
{
id,
}
)

const artwork = data.artwork as NonNullable<ArtworkGridItemSaveButtonQuery$data["artwork"]>

const onArtworkSavedOrUnSaved = (saved: boolean) => {
const params = {
acquireable: artwork.isAcquireable,
availability: artwork.availability,
biddable: artwork.isBiddable,
context_module: contextModule,
context_screen_owner_id: contextScreenOwnerId,
context_screen_owner_slug: contextScreenOwnerSlug,
context_screen_owner_type: contextScreenOwnerType,
context_screen: contextScreen,
inquireable: artwork.isInquireable,
offerable: artwork.isOfferable,
}
trackEvent(tracks.saveOrUnsaveArtwork(saved, params))
}

const handleArtworkSave = useSaveArtwork({
id: artwork.id,
internalID: id,
isSaved: !!data?.artwork?.isSaved,
onCompleted: onArtworkSavedOrUnSaved,
})

const { isSaved, saveArtworkToLists } = useSaveArtworkToArtworkLists({
artworkFragmentRef: artwork,
onCompleted: onArtworkSavedOrUnSaved,
})
if (!data.artwork) {
return null
}

return (
<Touchable
haptic
onPress={disableArtworksListPrompt ? handleArtworkSave : saveArtworkToLists}
testID="save-artwork-icon"
>
<ArtworkHeartIcon isSaved={!!isSaved} index={itemIndex} />
</Touchable>
)
}

const ArtworkHeartIcon: React.FC<{ isSaved: boolean | null; index?: number }> = ({
isSaved,
index,
}) => {
const iconProps = { height: HEART_ICON_SIZE, width: HEART_ICON_SIZE, testID: "empty-heart-icon" }

if (isSaved) {
return <HeartFillIcon {...iconProps} testID="filled-heart-icon" fill="blue100" />
}
if (index === 0) {
// We only try to show the save onboard Popover in the 1st element
return (
<ProgressiveOnboardingSaveArtwork>
<HeartIcon {...iconProps} />
</ProgressiveOnboardingSaveArtwork>
)
}
return <HeartIcon {...iconProps} />
}

export const ArtworkGridItemSaveButtonQueryRenderer = (props: ArtworkGridItemSaveButtonProps) => {
return (
<Suspense fallback={ArtworkHeartIcon}>
<ArtworkGridItemSaveButton {...props} />
</Suspense>
)
}
86 changes: 43 additions & 43 deletions src/app/Scenes/HomeView/Sections/Section.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,54 +42,54 @@ export const Section: React.FC<SectionProps> = ({ section, ...rest }) => {
}

switch (section.component?.type) {
case "FeaturedCollection":
return (
<HomeViewSectionFeaturedCollectionQueryRenderer sectionID={section.internalID} {...rest} />
)
case "ArticlesCard":
return <HomeViewSectionArticlesCardsQueryRenderer sectionID={section.internalID} {...rest} />
// case "FeaturedCollection":
// return (
// <HomeViewSectionFeaturedCollectionQueryRenderer sectionID={section.internalID} {...rest} />
// )
// case "ArticlesCard":
// return <HomeViewSectionArticlesCardsQueryRenderer sectionID={section.internalID} {...rest} />
case "Chips":
return <HomeViewSectionCardsChipsQueryRenderer sectionID={section.internalID} {...rest} />
}

switch (section.__typename) {
case "HomeViewSectionActivity":
return <HomeViewSectionActivityQueryRenderer sectionID={section.internalID} {...rest} />
case "HomeViewSectionArtworks":
return <HomeViewSectionArtworksQueryRenderer sectionID={section.internalID} {...rest} />
case "HomeViewSectionCard":
return <HomeViewSectionCardQueryRenderer sectionID={section.internalID} {...rest} />
case "HomeViewSectionGeneric":
return <HomeViewSectionGeneric section={section} {...rest} />
case "HomeViewSectionArticles":
return <HomeViewSectionArticlesQueryRenderer sectionID={section.internalID} {...rest} />
case "HomeViewSectionArtists":
return <HomeViewSectionArtistsQueryRenderer sectionID={section.internalID} {...rest} />
case "HomeViewSectionAuctionResults":
return <HomeViewSectionAuctionResultsQueryRenderer sectionID={section.internalID} {...rest} />
case "HomeViewSectionHeroUnits":
return <HomeViewSectionHeroUnitsQueryRenderer sectionID={section.internalID} {...rest} />
case "HomeViewSectionCards":
return <HomeViewSectionCardsQueryRenderer sectionID={section.internalID} {...rest} />
case "HomeViewSectionFairs":
return <HomeViewSectionFairsQueryRenderer sectionID={section.internalID} {...rest} />
case "HomeViewSectionMarketingCollections":
return (
<HomeViewSectionMarketingCollectionsQueryRenderer
sectionID={section.internalID}
{...rest}
/>
)
case "HomeViewSectionShows":
return <HomeViewSectionShowsQueryRenderer sectionID={section.internalID} {...rest} />
case "HomeViewSectionViewingRooms":
return <HomeViewSectionViewingRoomsQueryRenderer sectionID={section.internalID} {...rest} />
case "HomeViewSectionSales":
return <HomeViewSectionSalesQueryRenderer sectionID={section.internalID} {...rest} />
case "HomeViewSectionTasks":
return enableHomeViewTasksSection ? (
<HomeViewSectionTasksQueryRenderer sectionID={section.internalID} {...rest} />
) : null
// case "HomeViewSectionActivity":
// return <HomeViewSectionActivityQueryRenderer sectionID={section.internalID} {...rest} />
// case "HomeViewSectionArtworks":
// return <HomeViewSectionArtworksQueryRenderer sectionID={section.internalID} {...rest} />
// case "HomeViewSectionCard":
// return <HomeViewSectionCardQueryRenderer sectionID={section.internalID} {...rest} />
// case "HomeViewSectionGeneric":
// return <HomeViewSectionGeneric section={section} {...rest} />
// case "HomeViewSectionArticles":
// return <HomeViewSectionArticlesQueryRenderer sectionID={section.internalID} {...rest} />
// case "HomeViewSectionArtists":
// return <HomeViewSectionArtistsQueryRenderer sectionID={section.internalID} {...rest} />
// case "HomeViewSectionAuctionResults":
// return <HomeViewSectionAuctionResultsQueryRenderer sectionID={section.internalID} {...rest} />
// case "HomeViewSectionHeroUnits":
// return <HomeViewSectionHeroUnitsQueryRenderer sectionID={section.internalID} {...rest} />
// case "HomeViewSectionCards":
// return <HomeViewSectionCardsQueryRenderer sectionID={section.internalID} {...rest} />
// case "HomeViewSectionFairs":
// return <HomeViewSectionFairsQueryRenderer sectionID={section.internalID} {...rest} />
// case "HomeViewSectionMarketingCollections":
// return (
// <HomeViewSectionMarketingCollectionsQueryRenderer
// sectionID={section.internalID}
// {...rest}
// />
// )
// case "HomeViewSectionShows":
// return <HomeViewSectionShowsQueryRenderer sectionID={section.internalID} {...rest} />
// case "HomeViewSectionViewingRooms":
// return <HomeViewSectionViewingRoomsQueryRenderer sectionID={section.internalID} {...rest} />
// case "HomeViewSectionSales":
// return <HomeViewSectionSalesQueryRenderer sectionID={section.internalID} {...rest} />
// case "HomeViewSectionTasks":
// return enableHomeViewTasksSection ? (
// <HomeViewSectionTasksQueryRenderer sectionID={section.internalID} {...rest} />
// ) : null
default:
if (__DEV__) {
return (
Expand Down
1 change: 1 addition & 0 deletions src/app/system/ignoreLogs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@ LogBox.ignoreLogs([
// This is for the Artist page, which will likely get redone soon anyway.
"VirtualizedLists should never be nested inside plain ScrollViews with the same orientation - use another VirtualizedList-backed container instead.",
"Picker has been extracted",
"[Reanimated]",
])
Loading