diff --git a/src/app/Components/ArtworkRail/ArtworkRail.tsx b/src/app/Components/ArtworkRail/ArtworkRail.tsx
index 57357bacbe3..58df5b61315 100644
--- a/src/app/Components/ArtworkRail/ArtworkRail.tsx
+++ b/src/app/Components/ArtworkRail/ArtworkRail.tsx
@@ -1,4 +1,4 @@
-import { Box, Flex, Join, SkeletonBox, SkeletonText, Spacer } from "@artsy/palette-mobile"
+import { Box, Flex, SkeletonBox, SkeletonText, Spacer } from "@artsy/palette-mobile"
import { ListRenderItem } from "@shopify/flash-list"
import {
ArtworkRail_artworks$data,
@@ -16,12 +16,11 @@ import { LEGACY_ARTWORK_RAIL_CARD_IMAGE_HEIGHT } from "app/Components/ArtworkRai
import { BrowseMoreRailCard } from "app/Components/BrowseMoreRailCard"
import { PrefetchFlashList } from "app/Components/PrefetchFlashList"
import { useFeatureFlag } from "app/utils/hooks/useFeatureFlag"
-import { RandomWidthPlaceholderText, useMemoizedRandom } from "app/utils/placeholders"
+import { RandomWidthPlaceholderText } from "app/utils/placeholders"
import {
ArtworkActionTrackingProps,
extractArtworkActionTrackingProps,
} from "app/utils/track/ArtworkActions"
-import { times } from "lodash"
import React, { ReactElement, useCallback } from "react"
import { FlatList, ViewabilityConfig } from "react-native"
import { isTablet } from "react-native-device-info"
@@ -142,10 +141,11 @@ export const ArtworkRailPlaceholder: React.FC = () => {
const enableArtworkRailRedesignImageAspectRatio = useFeatureFlag(
"AREnableArtworkRailRedesignImageAspectRatio"
)
+ const cards = !isTablet() ? 2 : 6
return (
- }>
- {times(3 + useMemoizedRandom() * 10).map((index) => (
+
+ {Array.from({ length: cards }).map((_, index) => (
{enableArtworkRailRedesignImageAspectRatio ? (
{
))}
-
+
)
}
diff --git a/src/app/Scenes/CollectionsByCategory/Body.tsx b/src/app/Scenes/CollectionsByCategory/Body.tsx
index 7f53f41caa6..a2c8e6286d4 100644
--- a/src/app/Scenes/CollectionsByCategory/Body.tsx
+++ b/src/app/Scenes/CollectionsByCategory/Body.tsx
@@ -1,36 +1,59 @@
import { Flex, Skeleton, SkeletonText, Text, useSpace } from "@artsy/palette-mobile"
import { useRoute } from "@react-navigation/native"
import { BodyCollectionsByCategoryQuery } from "__generated__/BodyCollectionsByCategoryQuery.graphql"
+import { BodyCollectionsByCategory_marketingCollection$key } from "__generated__/BodyCollectionsByCategory_marketingCollection.graphql"
import { CollectionsChips_marketingCollections$key } from "__generated__/CollectionsChips_marketingCollections.graphql"
+import {
+ CollectionRailPlaceholder,
+ CollectionRailWithSuspense,
+} from "app/Scenes/CollectionsByCategory/CollectionRail"
import { CollectionsByCategoriesRouteProp } from "app/Scenes/CollectionsByCategory/CollectionsByCategory"
import {
CollectionsChips,
CollectionsChipsPlaceholder,
} from "app/Scenes/CollectionsByCategory/CollectionsChips"
import { NoFallback, withSuspense } from "app/utils/hooks/withSuspense"
-import { graphql, useLazyLoadQuery } from "react-relay"
+import { graphql, useLazyLoadQuery, useFragment } from "react-relay"
interface BodyProps {
- marketingCollections: CollectionsChips_marketingCollections$key
+ marketingCollections: BodyCollectionsByCategory_marketingCollection$key &
+ CollectionsChips_marketingCollections$key
}
-export const Body: React.FC = ({ marketingCollections }) => {
+export const Body: React.FC = ({ marketingCollections: _marketingCollections }) => {
const space = useSpace()
+ const marketingCollections = useFragment(fragment, _marketingCollections)
const { params } = useRoute()
const category = params.props.category
+ if (!marketingCollections) {
+ return null
+ }
+
return (
-
+
{category}
Explore collections with {category}
-
+
+
+ {marketingCollections.map((collection) => {
+ const slug = collection?.slug ?? ""
+ return
+ })}
)
}
+const fragment = graphql`
+ fragment BodyCollectionsByCategory_marketingCollection on MarketingCollection
+ @relay(plural: true) {
+ slug @required(action: NONE)
+ }
+`
+
const BodyPlaceholder: React.FC = () => {
const space = useSpace()
@@ -44,6 +67,8 @@ const BodyPlaceholder: React.FC = () => {
+
+
)
@@ -51,7 +76,8 @@ const BodyPlaceholder: React.FC = () => {
const query = graphql`
query BodyCollectionsByCategoryQuery($category: String!) {
- marketingCollections(category: $category, size: 10) {
+ marketingCollections(category: $category, first: 20) {
+ ...BodyCollectionsByCategory_marketingCollection
...CollectionsChips_marketingCollections
}
}
diff --git a/src/app/Scenes/CollectionsByCategory/CollectionRail.tsx b/src/app/Scenes/CollectionsByCategory/CollectionRail.tsx
new file mode 100644
index 00000000000..ce0539450f8
--- /dev/null
+++ b/src/app/Scenes/CollectionsByCategory/CollectionRail.tsx
@@ -0,0 +1,127 @@
+import {
+ ArrowRightIcon,
+ Flex,
+ Skeleton,
+ SkeletonText,
+ Spacer,
+ useScreenDimensions,
+} from "@artsy/palette-mobile"
+import { CollectionRailCollectionsByCategoryQuery } from "__generated__/CollectionRailCollectionsByCategoryQuery.graphql"
+import { CollectionRail_marketingCollection$key } from "__generated__/CollectionRail_marketingCollection.graphql"
+import { ArtworkRail, ArtworkRailPlaceholder } from "app/Components/ArtworkRail/ArtworkRail"
+import { SectionTitle } from "app/Components/SectionTitle"
+import { ElementInView } from "app/utils/ElementInView"
+import { extractNodes } from "app/utils/extractNodes"
+import { withSuspense, NoFallback } from "app/utils/hooks/withSuspense"
+import { useClientQuery } from "app/utils/useClientQuery"
+import { FC, useState } from "react"
+import { graphql, useFragment } from "react-relay"
+
+interface CollectionRailProps {
+ collection: CollectionRail_marketingCollection$key
+}
+
+export const CollectionRail: FC = ({ collection: _collection }) => {
+ const collection = useFragment(fragment, _collection)
+
+ if (!collection || collection.artworksConnection?.counts.total === 0) {
+ return null
+ }
+
+ const artworks = extractNodes(collection.artworksConnection)
+
+ return (
+
+ {}}
+ RightButtonContent={() => }
+ />
+
+
+ )
+}
+
+const fragment = graphql`
+ fragment CollectionRail_marketingCollection on MarketingCollection {
+ title @required(action: NONE)
+
+ artworksConnection(first: 10) {
+ counts @required(action: NONE) {
+ total
+ }
+ edges {
+ node {
+ ...ArtworkRail_artworks
+
+ internalID
+ slug
+ href
+ }
+ }
+ }
+ }
+`
+
+export const CollectionRailPlaceholder: FC = () => {
+ return (
+
+
+ Category title
+
+
+
+
+
+
+
+
+
+ )
+}
+
+const query = graphql`
+ query CollectionRailCollectionsByCategoryQuery($slug: String!) {
+ marketingCollection(slug: $slug) {
+ ...CollectionRail_marketingCollection
+
+ title
+ markdownDescription
+ }
+ }
+`
+
+interface CollectionRailWithSuspenseProps {
+ slug: string
+}
+
+export const CollectionRailWithSuspense = withSuspense({
+ Component: ({ slug }) => {
+ const { height } = useScreenDimensions()
+ const [isVisible, setIsVisible] = useState(false)
+ const { data, loading } = useClientQuery({
+ query,
+ variables: { slug },
+ skip: !isVisible,
+ })
+
+ const handleOnVisible = () => {
+ if (!isVisible) {
+ setIsVisible(true)
+ }
+ }
+
+ if (loading || !data?.marketingCollection || !isVisible) {
+ // We don't need to overfetch all rails at once, fetch as they become closer to be visible
+ return (
+
+
+
+ )
+ }
+
+ return
+ },
+ ErrorFallback: NoFallback,
+ LoadingFallback: CollectionRailPlaceholder,
+})
diff --git a/src/app/Scenes/CollectionsByCategory/__tests__/Body.tests.tsx b/src/app/Scenes/CollectionsByCategory/__tests__/Body.tests.tsx
new file mode 100644
index 00000000000..499d00ed329
--- /dev/null
+++ b/src/app/Scenes/CollectionsByCategory/__tests__/Body.tests.tsx
@@ -0,0 +1,39 @@
+import { screen } from "@testing-library/react-native"
+import { BodyHomeViewSectionCardsTestQuery } from "__generated__/BodyHomeViewSectionCardsTestQuery.graphql"
+import { Body } from "app/Scenes/CollectionsByCategory/Body"
+import { setupTestWrapper } from "app/utils/tests/setupTestWrapper"
+import { graphql } from "react-relay"
+
+jest.mock("@react-navigation/native", () => ({
+ useRoute: () => ({
+ params: {
+ props: { category: "mock-category" },
+ },
+ }),
+}))
+
+jest.mock("app/Scenes/CollectionsByCategory/CollectionRail", () => ({
+ CollectionRailWithSuspense: () => null,
+ CollectionRailPlaceholder: () => null,
+}))
+
+describe("Body", () => {
+ const { renderWithRelay } = setupTestWrapper({
+ Component: ({ marketingCollections }) => ,
+ query: graphql`
+ query BodyHomeViewSectionCardsTestQuery {
+ marketingCollections(category: "category", first: 20) @required(action: NONE) {
+ ...BodyCollectionsByCategory_marketingCollection
+ ...CollectionsChips_marketingCollections
+ }
+ }
+ `,
+ })
+
+ it("renders", () => {
+ renderWithRelay()
+
+ expect(screen.getByText(/Explore collections with mock-category/)).toBeOnTheScreen()
+ expect(screen.getByText(//)).toBeOnTheScreen()
+ })
+})
diff --git a/src/app/Scenes/CollectionsByCategory/__tests__/CollectionRail.tests.tsx b/src/app/Scenes/CollectionsByCategory/__tests__/CollectionRail.tests.tsx
new file mode 100644
index 00000000000..80e5ba538db
--- /dev/null
+++ b/src/app/Scenes/CollectionsByCategory/__tests__/CollectionRail.tests.tsx
@@ -0,0 +1,29 @@
+import { screen } from "@testing-library/react-native"
+import { CollectionRailHomeViewSectionCardsTestQuery } from "__generated__/CollectionRailHomeViewSectionCardsTestQuery.graphql"
+import { CollectionRail } from "app/Scenes/CollectionsByCategory/CollectionRail"
+import { setupTestWrapper } from "app/utils/tests/setupTestWrapper"
+import { graphql } from "react-relay"
+
+jest.mock("app/Components/ArtworkRail/ArtworkRail", () => ({
+ ArtworkRail: () => null,
+ ArtworkRailPlaceholder: () => null,
+}))
+
+describe("CollectionRail", () => {
+ const { renderWithRelay } = setupTestWrapper({
+ Component: ({ marketingCollection }) => ,
+ query: graphql`
+ query CollectionRailHomeViewSectionCardsTestQuery {
+ marketingCollection(slug: "marketing-slug") @required(action: NONE) {
+ ...CollectionRail_marketingCollection
+ }
+ }
+ `,
+ })
+
+ it("renders", () => {
+ renderWithRelay()
+
+ expect(screen.getByText(/mock-Value-for-Field-"Title"/)).toBeOnTheScreen()
+ })
+})
diff --git a/src/app/Scenes/Home/Home.tsx b/src/app/Scenes/Home/Home.tsx
index 8dd98622760..a212fb528b7 100644
--- a/src/app/Scenes/Home/Home.tsx
+++ b/src/app/Scenes/Home/Home.tsx
@@ -680,9 +680,8 @@ const HomePlaceholder: React.FC = () => {
-
-
-
+
+