From 8cb6c70a2df827a75965620149f7fdebd4fe1d78 Mon Sep 17 00:00:00 2001 From: Mounir Dhahri Date: Wed, 7 Jun 2023 22:11:10 +0200 Subject: [PATCH] chore: use collapsible tab views inside profile tab (#8820) * refactor: remove setJSX from Profile Tab * refactor: use palette sticky tabs inside my c * chore: remove visual clues related code * feat(tabs): Add tab notification support to MyCollection (#8823) * feat(notifications): add tab notification support * fix(indicators): make positioning right * fix(myc): use screen component --------- Co-authored-by: Christopher Pappas --- .secrets.baseline | 4 +- .../StickyTabPagePlaceholder.tsx | 16 ---- src/app/Scenes/ArtworkLists/ArtworkLists.tsx | 20 +++-- src/app/Scenes/Favorites/FavoriteArtworks.tsx | 49 +++++++----- .../Components/MyCollectionSearchBar.tsx | 23 +----- .../Components/MyCollectionStickyHeader.tsx | 62 ++++++--------- .../MyCollection/MyCollection.tests.tsx | 2 - src/app/Scenes/MyCollection/MyCollection.tsx | 76 +++++++----------- .../MyCollection/MyCollectionArtworks.tsx | 45 +---------- .../MyCollectionArtworkUploadMessages.tsx | 2 +- ...AuctionResultsForArtistsYouCollectRail.tsx | 4 +- .../Insights/MedianAuctionPriceRail.tsx | 2 + .../Screens/Insights/MyCollectionInsights.tsx | 63 +++++++-------- ...ProfileHeaderMyCollectionAndSavedWorks.tsx | 78 +++++++++---------- 14 files changed, 172 insertions(+), 274 deletions(-) delete mode 100644 src/app/Components/StickyTabPage/StickyTabPagePlaceholder.tsx diff --git a/.secrets.baseline b/.secrets.baseline index 19e29418def..c6ecb500fdb 100644 --- a/.secrets.baseline +++ b/.secrets.baseline @@ -288,7 +288,7 @@ "filename": "src/app/Scenes/MyCollection/MyCollection.tests.tsx", "hashed_secret": "6414700358f2ae5762917a164e2e30df8783fc4e", "is_verified": false, - "line_number": 144 + "line_number": 142 } ], "src/app/Scenes/MyCollection/Screens/ArtworkForm/MyCollectionArtworkForm.tests.tsx": [ @@ -1035,5 +1035,5 @@ } ] }, - "generated_at": "2023-05-26T18:47:03Z" + "generated_at": "2023-06-06T15:05:27Z" } diff --git a/src/app/Components/StickyTabPage/StickyTabPagePlaceholder.tsx b/src/app/Components/StickyTabPage/StickyTabPagePlaceholder.tsx deleted file mode 100644 index 65eb9d476c6..00000000000 --- a/src/app/Components/StickyTabPage/StickyTabPagePlaceholder.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import { Flex, Spinner } from "@artsy/palette-mobile" -import { StickyTabPageScrollView } from "app/Components/StickyTabPage/StickyTabPageScrollView" - -export const StickyTabPagePlaceholder: React.FC = () => { - return ( - - - - - - ) -} diff --git a/src/app/Scenes/ArtworkLists/ArtworkLists.tsx b/src/app/Scenes/ArtworkLists/ArtworkLists.tsx index 9092803d424..7d8954108da 100644 --- a/src/app/Scenes/ArtworkLists/ArtworkLists.tsx +++ b/src/app/Scenes/ArtworkLists/ArtworkLists.tsx @@ -1,15 +1,13 @@ -import { Flex, Spacer, Spinner, useScreenDimensions, useSpace } from "@artsy/palette-mobile" +import { Flex, Spacer, Spinner, Tabs, useScreenDimensions, useSpace } from "@artsy/palette-mobile" import { ArtworkListsQuery } from "__generated__/ArtworkListsQuery.graphql" import { ArtworkLists_collectionsConnection$key } from "__generated__/ArtworkLists_collectionsConnection.graphql" import { GenericGridPlaceholder } from "app/Components/ArtworkGrids/GenericGrid" -import { StickTabPageRefreshControl } from "app/Components/StickyTabPage/StickTabPageRefreshControl" -import { StickyTabPageFlatList } from "app/Components/StickyTabPage/StickyTabPageFlatList" -import { StickyTabPageScrollView } from "app/Components/StickyTabPage/StickyTabPageScrollView" import { ArtworkListItem } from "app/Scenes/ArtworkLists/ArtworkListItem" import { useArtworkListsColCount } from "app/Scenes/ArtworkLists/useArtworkListsColCount" import { extractNodes } from "app/utils/extractNodes" import { isPad } from "app/utils/hardware" import { Suspense, useState } from "react" +import { RefreshControl } from "react-native" import { graphql, useLazyLoadQuery, usePaginationFragment } from "react-relay" /** @@ -81,16 +79,16 @@ export const ArtworkLists = () => { }) return ( - item.content} numColumns={artworkListsColCount} keyExtractor={(item) => item.key} onEndReached={handleLoadMore} ListFooterComponent={!!hasNext ? : } - refreshControl={ - - } + refreshControl={} /> ) } @@ -113,9 +111,9 @@ export const ArtworkListsPlaceHolder = () => { const screen = useScreenDimensions() const space = useSpace() return ( - + - + ) } diff --git a/src/app/Scenes/Favorites/FavoriteArtworks.tsx b/src/app/Scenes/Favorites/FavoriteArtworks.tsx index 60dc2bbc9fd..38ac4051f25 100644 --- a/src/app/Scenes/Favorites/FavoriteArtworks.tsx +++ b/src/app/Scenes/Favorites/FavoriteArtworks.tsx @@ -1,10 +1,9 @@ -import { Spacer, useSpace, Button } from "@artsy/palette-mobile" +import { Button, Spacer, Tabs, useSpace } from "@artsy/palette-mobile" import { FavoriteArtworksQuery } from "__generated__/FavoriteArtworksQuery.graphql" import { FavoriteArtworks_me$data } from "__generated__/FavoriteArtworks_me.graphql" import GenericGrid, { GenericGridPlaceholder } from "app/Components/ArtworkGrids/GenericGrid" import { LoadFailureView } from "app/Components/LoadFailureView" import { ZeroState } from "app/Components/States/ZeroState" -import { StickTabPageRefreshControl } from "app/Components/StickyTabPage/StickTabPageRefreshControl" import { StickyTabPageScrollView } from "app/Components/StickyTabPage/StickyTabPageScrollView" import { PAGE_SIZE } from "app/Components/constants" import { navigate } from "app/system/navigation/navigate" @@ -14,8 +13,8 @@ import { useScreenDimensions } from "app/utils/hooks" import { FAVORITE_ARTWORKS_REFRESH_KEY, RefreshEvents } from "app/utils/refreshHelpers" import { renderWithPlaceholder } from "app/utils/renderWithPlaceholder" import { useEffect, useState } from "react" -import { Image } from "react-native" -import { createPaginationContainer, graphql, QueryRenderer, RelayPaginationProp } from "react-relay" +import { Image, RefreshControl } from "react-native" +import { QueryRenderer, RelayPaginationProp, createPaginationContainer, graphql } from "react-relay" interface Props { me: FavoriteArtworks_me$data @@ -74,9 +73,9 @@ const SavedWorks: React.FC = ({ me, relay, onDataFetching }) => { if (artworks.length === 0) { return ( - + } contentContainerStyle={{ flexGrow: 1, justifyContent: "center", height: "100%" }} > @@ -102,27 +101,35 @@ const SavedWorks: React.FC = ({ me, relay, onDataFetching }) => { } /> - + ) } + const data = [ + { + content: ( + + ), + key: "grid", + }, + ] + return ( - - } - > - - + renderItem={({ item }) => item.content} + keyExtractor={({ key }) => key} + refreshControl={} + /> ) } diff --git a/src/app/Scenes/MyCollection/Components/MyCollectionSearchBar.tsx b/src/app/Scenes/MyCollection/Components/MyCollectionSearchBar.tsx index 037e2ff5283..758b264de1f 100644 --- a/src/app/Scenes/MyCollection/Components/MyCollectionSearchBar.tsx +++ b/src/app/Scenes/MyCollection/Components/MyCollectionSearchBar.tsx @@ -1,9 +1,8 @@ -import { Flex, useTheme, Text, useSpace } from "@artsy/palette-mobile" +import { Flex, INPUT_HEIGHT, Text, useSpace, useTheme } from "@artsy/palette-mobile" import { GridViewIcon } from "app/Components/Icons/GridViewIcon" import { ListViewIcon } from "app/Components/Icons/ListViewIcon" import SearchIcon from "app/Components/Icons/SearchIcon" import { Input } from "app/Components/Input" -import { useStickyTabPageContext } from "app/Components/StickyTabPage/StickyTabPageContext" import { useAnimatedValue } from "app/Components/StickyTabPage/reanimatedHelpers" import { ViewOption } from "app/Scenes/Search/UserPrefsModel" import { GlobalStore } from "app/store/GlobalStore" @@ -40,8 +39,6 @@ export const MyCollectionSearchBar: React.FC = ({ const [value, setValue] = useState(searchString) - const { staticHeaderHeight } = useStickyTabPageContext() - const viewOptionPreference = GlobalStore.useAppState((state) => state.userPrefs.artworkViewOption) const [viewOption, setViewOption] = useState(viewOptionPreference) @@ -61,26 +58,12 @@ export const MyCollectionSearchBar: React.FC = ({ GlobalStore.actions.userPrefs.setArtworkViewOption(selectedViewOption) } - Animated.useCode( - () => - Animated.call( - [staticHeaderHeight, hasRunFocusedAnimation], - ([, hasFinishedAnimationLoop]) => { - if (hasFinishedAnimationLoop) { - return - } - hasRunFocusedAnimation.setValue(new Animated.Value(1)) - } - ), - [isFocused] - ) - useEffect(() => { debouncedSetKeywordFilter(value) }, [value]) return ( - + {isFocused ? ( = ({ ) : ( - + void showNewWorksMessage: boolean - showSeparator: boolean } export const MyCollectionStickyHeader: React.FC = ({ @@ -52,7 +51,6 @@ export const MyCollectionStickyHeader: React.FC = hasMarketSignals, showModal, showNewWorksMessage, - showSeparator, }) => { const { showVisualClue } = useVisualClue() @@ -74,9 +72,7 @@ export const MyCollectionStickyHeader: React.FC = )} - {!!showArtworkFilters && ( - - )} + {!!showArtworkFilters && } void - showSeparator: boolean -}) => { +const Filters = ({ filtersCount, showModal }: { filtersCount: number; showModal: () => void }) => { const { trackEvent } = useTracking() return ( - - - + + + + + ) } diff --git a/src/app/Scenes/MyCollection/MyCollection.tests.tsx b/src/app/Scenes/MyCollection/MyCollection.tests.tsx index a81e7687547..bf36a993d2e 100644 --- a/src/app/Scenes/MyCollection/MyCollection.tests.tsx +++ b/src/app/Scenes/MyCollection/MyCollection.tests.tsx @@ -3,7 +3,6 @@ import { MyCollectionTestsQuery } from "__generated__/MyCollectionTestsQuery.gra import { ArtworkFiltersStoreProvider } from "app/Components/ArtworkFilter/ArtworkFilterStore" import { InfiniteScrollMyCollectionArtworksGridContainer } from "app/Components/ArtworkGrids/InfiniteScrollArtworksGrid" import { StickyTabPage } from "app/Components/StickyTabPage/StickyTabPage" -import { StickyTabPageScrollView } from "app/Components/StickyTabPage/StickyTabPageScrollView" import { MyCollectionTabsStoreProvider } from "app/Scenes/MyCollection/State/MyCollectionTabsStore" import { Tab } from "app/Scenes/MyProfile/MyProfileHeaderMyCollectionAndSavedWorks" @@ -106,7 +105,6 @@ describe("MyCollection", () => { describe("collection is not empty", () => { it("renders without throwing an error", () => { const tree = renderWithRelay() - expect(tree.UNSAFE_getByType(StickyTabPageScrollView)).toBeDefined() expect(tree.UNSAFE_getByType(InfiniteScrollMyCollectionArtworksGridContainer)).toBeDefined() }) }) diff --git a/src/app/Scenes/MyCollection/MyCollection.tsx b/src/app/Scenes/MyCollection/MyCollection.tsx index bda06f514a9..c2559b8d304 100644 --- a/src/app/Scenes/MyCollection/MyCollection.tsx +++ b/src/app/Scenes/MyCollection/MyCollection.tsx @@ -1,5 +1,5 @@ import { OwnerType } from "@artsy/cohesion" -import { Button, Flex, Separator, Spacer } from "@artsy/palette-mobile" +import { Button, Flex, Separator, Spacer, Tabs } from "@artsy/palette-mobile" import AsyncStorage from "@react-native-async-storage/async-storage" import { InfiniteScrollArtworksGrid_myCollectionConnection$data } from "__generated__/InfiniteScrollArtworksGrid_myCollectionConnection.graphql" import { MyCollectionFetchAuctionResultsQuery } from "__generated__/MyCollectionFetchAuctionResultsQuery.graphql" @@ -9,9 +9,6 @@ import { ArtworkFilterNavigator, FilterModalMode } from "app/Components/ArtworkF import { ArtworkFiltersStoreProvider } from "app/Components/ArtworkFilter/ArtworkFilterStore" import { useSelectedFiltersCount } from "app/Components/ArtworkFilter/useArtworkFilters" import { LoadFailureView } from "app/Components/LoadFailureView" -import { StickTabPageRefreshControl } from "app/Components/StickyTabPage/StickTabPageRefreshControl" -import { StickyTabPageFlatListContext } from "app/Components/StickyTabPage/StickyTabPageFlatList" -import { StickyTabPageScrollView } from "app/Components/StickyTabPage/StickyTabPageScrollView" import { useToast } from "app/Components/Toast/toastHook" import { PAGE_SIZE } from "app/Components/constants" import { MyCollectionCollectedArtists } from "app/Scenes/MyCollection/Components/MyCollectionCollectedArtists" @@ -40,7 +37,8 @@ import { renderWithPlaceholder } from "app/utils/renderWithPlaceholder" import { ProvideScreenTrackingWithCohesionSchema } from "app/utils/track" import { screen } from "app/utils/track/helpers" import { times } from "lodash" -import React, { useContext, useEffect, useRef, useState } from "react" +import React, { useEffect, useState } from "react" +import { RefreshControl } from "react-native" import { QueryRenderer, RelayPaginationProp, @@ -65,8 +63,7 @@ const MyCollection: React.FC<{ const [hasMarketSignals, setHasMarketSignals] = useState(false) const [isFilterModalVisible, setIsFilterModalVisible] = useState(false) const [isRefreshing, setIsRefreshing] = useState(false) - const [showSearchBar, setShowSearchBar] = useState(false) - const innerFlatListRef = useRef(null) + const [showNewWorksMessage, setShowNewWorksMessage] = useState(false) const filtersCount = useSelectedFiltersCount() @@ -133,36 +130,21 @@ const MyCollection: React.FC<{ relay.loadMore(100) }, [me?.myCollectionConnection]) - // hack for tests. we should fix that. - const setJSX = useContext(StickyTabPageFlatListContext).setJSX - - const showMessages = async () => { - const showNewWorksMessage = + const checkForNewMessages = async () => { + const newWorksMessage = me.myCollectionInfo?.includesPurchasedArtworks && !(await AsyncStorage.getItem(HAS_SEEN_MY_COLLECTION_NEW_WORKS_BANNER)) - setJSX( - setIsFilterModalVisible(true)} - showNewWorksMessage={!!showNewWorksMessage} - showSeparator={!showSearchBar} - hasArtworks={artworks.length > 0} - /> - ) + setShowNewWorksMessage(!!newWorksMessage) } useEffect(() => { const renderMessages = enableCollectedArtists ? hasCollectedArtists : artworks.length if (renderMessages) { - showMessages() - } else { - // remove already set JSX - setJSX(null) + checkForNewMessages() } - }, [artworks.length, filtersCount, showSearchBar]) + }, [artworks.length, filtersCount]) useEffect(() => { reInitializeLocalArtworkFilter(artworks) @@ -176,7 +158,7 @@ const MyCollection: React.FC<{ // User has no artworks but has manually added collected artists if (artworks.length === 0 && hasCollectedArtists) { return ( - + {selectedTab === null && ( <> @@ -184,36 +166,41 @@ const MyCollection: React.FC<{ )} - + ) } return ( - } - innerRef={innerFlatListRef} + } keyboardDismissMode="on-drag" keyboardShouldPersistTaps="handled" - paddingHorizontal={0} > + + setIsFilterModalVisible(true)} + showNewWorksMessage={!!showNewWorksMessage} + hasArtworks={artworks.length > 0} + /> + setIsFilterModalVisible(false)} exitModal={() => setIsFilterModalVisible(false)} /> + + + {(selectedTab === null || selectedTab === "Artists") && enableCollectedArtists ? ( ) : null} {selectedTab === null || selectedTab === "Artworks" || !enableCollectedArtists ? ( - + ) : null} {!!showDevAddButton && (