From 6c297bb7a64ab8d5f39263aa1f5dd95da9388872 Mon Sep 17 00:00:00 2001 From: Mounir Dhahri Date: Wed, 4 Dec 2024 18:29:16 +0100 Subject: [PATCH] chore: remove old navigation code [part 1] (#11245) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: remove old navigation code [part 1] * fix: tests - round 1 * fix: tests - round 2 * fix: tests - round 3 * fix: header on settings screen * fix: remove non used modules * fix: remove typo Ø --- docs/best_practices.md | 12 +- src/app/App.tsx | 24 +- src/app/AppRegistry.tsx | 330 +++--------------- .../Artist/ArtistAbout/ArtistAbout.tests.tsx | 7 +- src/app/Components/ArtsyWebView.tsx | 29 +- .../AutosuggestResults.tests.tsx | 2 - src/app/Components/Containers/BidFlow.tsx | 17 +- src/app/Components/Containers/Inquiry.tsx | 38 +- src/app/Components/LoadFailureView.tsx | 16 +- ...rogressiveOnboardingAlertFilters.tests.tsx | 1 + ...essiveOnboardingFindSavedArtwork.tests.tsx | 1 + ...ogressiveOnboardingOfferSettings.tests.tsx | 1 + .../ProgressiveOnboardingSaveAlert.tests.tsx | 1 + ...ProgressiveOnboardingSaveArtwork.tests.tsx | 1 + ...gressiveOnboardingSignalInterest.tests.tsx | 1 + .../useDismissSavedArtwork.tests.tsx | 1 + src/app/Components/Toast/ToastComponent.tsx | 6 +- .../NativeModules/ARScreenPresenterModule.tsx | 173 --------- src/app/NativeModules/LegacyNativeModules.tsx | 16 - .../AuthenticatedRoutes/StackNavigator.tsx | 3 - src/app/Navigation/Utils/isHeaderShown.tsx | 5 - src/app/Providers.tsx | 7 +- src/app/Scenes/About/About.tsx | 41 +-- src/app/Scenes/Artist/Artist.tests.tsx | 16 +- src/app/Scenes/Artwork/Artwork.tests.tsx | 79 ++--- .../Components/ArtworkConsignments.tests.tsx | 7 +- .../ArtworkExtraLinks/index.tests.tsx | 7 +- .../Components/CertificateAuthenticity.tsx | 33 +- .../ArtworkAttributionClassFAQ.tsx | 34 +- .../Scenes/ArtworkMedium/ArtworkMedium.tsx | 34 +- .../Scenes/AuctionResult/AuctionResult.tsx | 23 +- .../Scenes/BottomTabs/BottomTabs.tests.tsx | 228 ------------ src/app/Scenes/BottomTabs/BottomTabs.tsx | 61 ---- .../BottomTabs/BottomTabsButton.tests.tsx | 80 ----- .../Scenes/BottomTabs/BottomTabsButton.tsx | 238 ------------- .../BottomTabs/BottomTabsNavigator.tests.tsx | 30 -- .../Scenes/BottomTabs/BottomTabsNavigator.tsx | 54 --- .../BottomTabs/useBottomTabBarHeight.ts | 10 - .../Components/FullFeaturedArtistList.tsx | 46 +-- .../__tests__/Body.tests.tsx | 1 + .../__tests__/Footer.tests.tsx | 1 + .../__tests__/Header.tests.tsx | 1 + .../__tests__/PaymentFailureBanner.tests.tsx | 1 + src/app/Scenes/HomeView/HomeView.tsx | 2 +- src/app/Scenes/Inbox/Screens/Conversation.tsx | 39 ++- .../Inbox/Screens/ConversationDetails.tsx | 39 +-- src/app/Scenes/MyAccount/MyAccount.tests.tsx | 4 - src/app/Scenes/MyAccount/MyAccount.tsx | 208 ++++++----- .../Scenes/MyAccount/MyAccountEditEmail.tsx | 39 +-- .../MyAccount/MyAccountEditPassword.tests.tsx | 4 - .../MyAccount/MyAccountEditPassword.tsx | 91 ++--- .../Scenes/MyAccount/MyAccountEditPhone.tsx | 46 +-- .../MyAccountEditPriceRange.tests.tsx | 4 - .../MyAccount/MyAccountEditPriceRange.tsx | 44 +-- .../Insights/CareerHighlightBottomSheet.tsx | 8 +- .../CareerHighlightsBigCardsSwiper.tsx | 17 +- .../MyCollectionAddCollectedArtists.tsx | 13 +- .../Scenes/MyProfile/MyProfileEditForm.tsx | 23 +- src/app/Scenes/MyProfile/MyProfilePayment.tsx | 43 +-- .../MyProfilePaymentNewCreditCard.tsx | 15 +- .../MyProfile/MyProfilePushNotifications.tsx | 44 +-- .../MyProfile/MyProfileSettings.tests.tsx | 7 - .../Scenes/MyProfile/MyProfileSettings.tsx | 24 +- .../__tests__/LoginWelcomeStep.tests.tsx | 20 +- .../scenes/__tests__/SignUpNameStep.tests.tsx | 30 +- src/app/Scenes/Onboarding/Onboarding.tsx | 36 +- .../OrderDetails/Components/OrderDetails.tsx | 44 +-- src/app/Scenes/OrderHistory/OrderHistory.tsx | 48 +-- src/app/Scenes/Search/Search.tsx | 2 +- .../SellWithArtsy/SellWithArtsyHome.tsx | 2 +- src/app/routes.ts | 4 +- src/app/store/GlobalStore.tsx | 20 -- src/app/store/config/features.ts | 6 - src/app/system/devTools/DevMenu/DevMenu.tsx | 40 +-- src/app/system/navigation/ModalStack.tsx | 152 -------- src/app/system/navigation/NavStack.tsx | 134 ------- src/app/system/navigation/navigate.tests.tsx | 254 +++----------- src/app/system/navigation/navigate.ts | 174 +++------ src/app/utils/bottomTabsHelper.tsx | 30 +- src/app/utils/hooks/useBackHandler.ts | 35 +- src/app/utils/hooks/useSelectedTab.ts | 26 +- .../utils/tests/NavigationTestsProvider.tsx | 13 + src/app/utils/tests/renderWithWrappers.tsx | 16 +- src/app/utils/useTabBarBadge.ts | 3 +- src/setupJest.tsx | 24 -- 85 files changed, 645 insertions(+), 2899 deletions(-) delete mode 100644 src/app/NativeModules/ARScreenPresenterModule.tsx delete mode 100644 src/app/Navigation/Utils/isHeaderShown.tsx delete mode 100644 src/app/Scenes/BottomTabs/BottomTabs.tests.tsx delete mode 100644 src/app/Scenes/BottomTabs/BottomTabs.tsx delete mode 100644 src/app/Scenes/BottomTabs/BottomTabsButton.tests.tsx delete mode 100644 src/app/Scenes/BottomTabs/BottomTabsButton.tsx delete mode 100644 src/app/Scenes/BottomTabs/BottomTabsNavigator.tests.tsx delete mode 100644 src/app/Scenes/BottomTabs/BottomTabsNavigator.tsx delete mode 100644 src/app/Scenes/BottomTabs/useBottomTabBarHeight.ts delete mode 100644 src/app/system/navigation/ModalStack.tsx delete mode 100644 src/app/system/navigation/NavStack.tsx create mode 100644 src/app/utils/tests/NavigationTestsProvider.tsx diff --git a/docs/best_practices.md b/docs/best_practices.md index 26eb9ebd637..8199a1d8933 100644 --- a/docs/best_practices.md +++ b/docs/best_practices.md @@ -172,11 +172,7 @@ For adding a screen that corresponds to a page on artsy.net add a new route and See our documentation on adding a route for more details: [Adding a new route](https://github.com/artsy/eigen/blob/main/docs/adding_a_new_route.md) and to [create a new screen](https://github.com/artsy/eigen/blob/main/docs/adding_a_new_screen.md). -### iOS Navigation - -- For native iOS code we use the **ARScreenPresenterModule**. Once the new app shell is finished (expected March 2022), we will be using `react-navigation`. - -For the most part you don't have to worry about this. +[For Artsy Engineers] If you want to learn more about our navigation infra, take a look at this [recording](https://drive.google.com/drive/u/0/folders/1wUAUHt86WLQMy7Fx3MU7k4bj4y1ngaCk) ## Analytics and tracking @@ -326,9 +322,3 @@ The following parts of the iOS app are handled in native code: - Analytics for Native UI. - View In Room (Augmented Reality) - City Guide Drawer Handling - -The following parts of the iOS app are handled in native code, but will be managed by React Native once the new app shell is finished (expected March 2022): - -- ARScreenPresenterModule to navigate between view controllers. -- The top-level tab bar, and each tab's navigation controller. -- Deep-link and notification handling. diff --git a/src/app/App.tsx b/src/app/App.tsx index 2c9a577fb52..316bcdc6581 100644 --- a/src/app/App.tsx +++ b/src/app/App.tsx @@ -6,10 +6,7 @@ import { codePushOptions } from "app/system/codepush" import { DevMenuWrapper } from "app/system/devTools/DevMenu/DevMenuWrapper" import { useRageShakeDevMenu } from "app/system/devTools/useRageShakeDevMenu" import { setupSentry } from "app/system/errorReporting/setupSentry" -import { ModalStack } from "app/system/navigation/ModalStack" import { usePurgeCacheOnAppUpdate } from "app/system/relay/usePurgeCacheOnAppUpdate" -import { useDevToggle } from "app/utils/hooks/useDevToggle" -import { useFeatureFlag } from "app/utils/hooks/useFeatureFlag" import { addTrackingProvider } from "app/utils/track" import { SEGMENT_TRACKING_PROVIDER, @@ -28,11 +25,8 @@ import Config from "react-native-config" import { Settings } from "react-native-fbsdk-next" import "react-native-get-random-values" import { useWebViewCookies } from "./Components/ArtsyWebView" -import { FPSCounter } from "./Components/FPSCounter" import { Providers } from "./Providers" -import { BottomTabsNavigator } from "./Scenes/BottomTabs/BottomTabsNavigator" import { ForceUpdate } from "./Scenes/ForceUpdate/ForceUpdate" -import { Onboarding } from "./Scenes/Onboarding/Onboarding" import { DynamicIslandStagingIndicator } from "./utils/DynamicIslandStagingIndicator" import { createAllChannels, savePendingToken } from "./utils/PushNotification" import { useInitializeQueryPrefetching } from "./utils/queryPrefetching" @@ -85,14 +79,10 @@ const Main = () => { ) const isLoggedIn = GlobalStore.useAppState((state) => !!state.auth.userAccessToken) - const onboardingState = GlobalStore.useAppState((state) => state.auth.onboardingState) const forceUpdateMessage = GlobalStore.useAppState( (state) => state.artsyPrefs.echo.forceUpdateMessage ) - const fpsCounter = useDevToggle("DTFPSCounter") - const useNewNavigation = useFeatureFlag("AREnableNewNavigation") - useStripeConfig() useSiftConfig() useWebViewCookies() @@ -126,19 +116,7 @@ const Main = () => { return } - if (useNewNavigation) { - return - } - if (!isLoggedIn || onboardingState === "incomplete") { - return - } - - return ( - - - {!!fpsCounter && } - - ) + return } const InnerApp = () => { diff --git a/src/app/AppRegistry.tsx b/src/app/AppRegistry.tsx index aa55bfea280..509d9415965 100644 --- a/src/app/AppRegistry.tsx +++ b/src/app/AppRegistry.tsx @@ -8,7 +8,6 @@ import { WorksForYouQueryRenderer, WorksForYouScreenQuery, } from "app/Components/Containers/WorksForYou" -import { FadeIn } from "app/Components/FadeIn" import { ActivityItemScreenQueryRenderer } from "app/Scenes/Activity/ActivityItemScreen" import { ArtQuiz } from "app/Scenes/ArtQuiz/ArtQuiz" import { ArtQuizResults } from "app/Scenes/ArtQuiz/ArtQuizResults/ArtQuizResults" @@ -24,6 +23,7 @@ import { CompleteMyProfile } from "app/Scenes/CompleteMyProfile/CompleteMyProfil import { GalleriesForYouScreen } from "app/Scenes/GalleriesForYou/GalleriesForYouScreen" import { HomeViewScreen, homeViewScreenQuery } from "app/Scenes/HomeView/HomeView" import { HomeViewSectionScreenQueryRenderer } from "app/Scenes/HomeViewSectionScreen/HomeViewSectionScreen" +import { ConversationQueryRenderer } from "app/Scenes/Inbox/Screens/Conversation" import { AddMyCollectionArtist } from "app/Scenes/MyCollection/Screens/Artist/AddMyCollectionArtist" import { MyCollectionArtworkEditQueryRenderer } from "app/Scenes/MyCollection/Screens/ArtworkForm/Screens/MyCollectionArtworkEdit" import { MyCollectionCollectedArtistsPrivacyQueryRenderer } from "app/Scenes/MyCollection/Screens/CollectedArtistsPrivacy/MyCollectionCollectedArtistsPrivacy" @@ -41,16 +41,12 @@ import { SubmitArtworkFormEditContainer } from "app/Scenes/SellWithArtsy/Artwork import { SimilarToRecentlyViewedScreen } from "app/Scenes/SimilarToRecentlyViewed/SimilarToRecentlyViewed" import { BackButton } from "app/system/navigation/BackButton" import { goBack } from "app/system/navigation/navigate" -import { ArtsyKeyboardAvoidingViewContext } from "app/utils/ArtsyKeyboardAvoidingView" -import { SafeAreaInsets, useScreenDimensions } from "app/utils/hooks" -import { useSelectedTab } from "app/utils/hooks/useSelectedTab" import React from "react" -import { AppRegistry, LogBox, Platform, View } from "react-native" +import { LogBox, View } from "react-native" import { GraphQLTaggedNode } from "react-relay" import { ArtsyWebViewPage } from "./Components/ArtsyWebView" import { CityGuideView } from "./NativeModules/CityGuideView" import { LiveAuctionView } from "./NativeModules/LiveAuctionView" -import { Providers } from "./Providers" import { About } from "./Scenes/About/About" import { ActivityScreen } from "./Scenes/Activity/ActivityScreen" import { ArticlesScreen, ArticlesScreenQuery } from "./Scenes/Articles/Articles" @@ -70,7 +66,7 @@ import { AuctionResultsForArtistsYouFollowPrefetchQuery, AuctionResultsForArtistsYouFollowQueryRenderer, } from "./Scenes/AuctionResults/AuctionResultsForArtistsYouFollow" -import { BottomTabOption, BottomTabType } from "./Scenes/BottomTabs/BottomTabType" +import { BottomTabType } from "./Scenes/BottomTabs/BottomTabType" import { CityView } from "./Scenes/City/City" import { CityFairListQueryRenderer } from "./Scenes/City/CityFairList" import { CityPicker } from "./Scenes/City/CityPicker" @@ -86,7 +82,6 @@ import { FeatureQueryRenderer } from "./Scenes/Feature/Feature" import { GeneQueryRenderer } from "./Scenes/Gene/Gene" import { MakeOfferModalQueryRenderer } from "./Scenes/Inbox/Components/Conversations/MakeOfferModal" import { PurchaseModalQueryRenderer } from "./Scenes/Inbox/Components/Conversations/PurchaseModal" -import { ConversationNavigator } from "./Scenes/Inbox/ConversationNavigator" import { ConversationDetailsQueryRenderer } from "./Scenes/Inbox/Screens/ConversationDetails" import { MapContainer } from "./Scenes/Map/MapContainer" import { MyAccountQueryRenderer } from "./Scenes/MyAccount/MyAccount" @@ -144,10 +139,7 @@ import { ViewingRoomsListScreen, viewingRoomsListScreenQuery, } from "./Scenes/ViewingRoom/ViewingRoomsList" -import { GlobalStore, unsafe_getFeatureFlag } from "./store/GlobalStore" -import { propsStore } from "./store/PropsStore" import { DevMenu } from "./system/devTools/DevMenu/DevMenu" -import { Schema, screenTrack } from "./utils/track" LogBox.ignoreLogs([ "Non-serializable values were found in the navigation state", @@ -157,148 +149,10 @@ LogBox.ignoreLogs([ ".removeListener(", // this is coming from https://github.com/facebook/react-native/blob/v0.68.0-rc.2/Libraries/AppState/AppState.js and other libs. ]) -interface PartnerLocationsProps { - partnerID: string - safeAreaInsets: SafeAreaInsets - isVisible: boolean -} -const PartnerLocations = (props: PartnerLocationsProps) => ( - -) - -interface InquiryProps { - artworkID: string -} -const Inquiry: React.FC = screenTrack((props) => { - return { - context_screen: Schema.PageNames.InquiryPage, - context_screen_owner_slug: props.artworkID, - context_screen_owner_type: Schema.OwnerEntityTypes.Artwork, - } -})((props) => ) - -interface ConversationProps { - conversationID: string -} -const Conversation: React.FC = screenTrack((props) => { - return { - context_screen: Schema.PageNames.ConversationPage, - context_screen_owner_id: props.conversationID, - context_screen_owner_type: Schema.OwnerEntityTypes.Conversation, - } -})(ConversationNavigator) - -interface PageWrapperProps { - fullBleed?: boolean - isMainView?: boolean - ignoreTabs?: boolean - ViewComponent: React.ComponentType - viewProps: any - moduleName: string -} - -const InnerPageWrapper: React.FC = ({ - fullBleed, - isMainView, - ignoreTabs = false, - ViewComponent, - viewProps, -}) => { - const safeAreaInsets = useScreenDimensions().safeAreaInsets - const paddingTop = fullBleed ? 0 : safeAreaInsets.top - const paddingBottom = isMainView ? 0 : safeAreaInsets.bottom - const isHydrated = GlobalStore.useAppState((state) => state.sessionState.isHydrated) - // if we're in a modal, just pass isVisible through - - let isVisible = viewProps.isVisible - if (!ignoreTabs) { - // eslint-disable-next-line react-hooks/rules-of-hooks - const currentTab = useSelectedTab() - if (BottomTabOption[viewProps.navStackID as BottomTabType]) { - // otherwise, make sure it respects the current tab - isVisible = isVisible && currentTab === viewProps.navStackID - } - } - - const isPresentedModally = viewProps.isPresentedModally - return ( - - - {isHydrated ? ( - - - - ) : null} - - - ) -} - -class PageWrapper extends React.Component { - pageProps: PageWrapperProps - - constructor(props: PageWrapperProps) { - super(props) - this.pageProps = this.savePageProps() - } - - componentDidUpdate() { - if (this.props.moduleName === "Map") { - // workaround for City Guide. DO NOT USE FOR OTHER THINGS! - // basically, only for the city guide component, we recreate the pageprops fresh. - // thats because of the funky way the native and RN components in city guide are set up. - // if we dont refresh them, then the city guide does not change cities from the dropdown. - this.pageProps = this.savePageProps() - } - } - - savePageProps() { - return { - ...this.props, - viewProps: { - ...this.props.viewProps, - ...propsStore.getPropsForModule(this.props.moduleName), - }, - } - } - - render() { - return ( - - - - ) - } -} - -function register( - screenName: string, - Component: React.ComponentType, - options?: Omit -) { - const WrappedComponent = (props: any) => ( - - ) - AppRegistry.registerComponent(screenName, () => WrappedComponent) -} - export interface ViewOptions { - // TODO: Remove this once the old infra code gets removed - modalPresentationStyle?: "fullScreen" | "pageSheet" | "formSheet" - // @deprecated Use screenOptions.headerShown instead - // TODO: Remove this once the old infra code gets removed - hasOwnModalCloseButton?: boolean alwaysPresentModally?: boolean // @deprecated Use screenOptions.headerShown instead - // TODO: Remove this once the old infra code gets removed - hidesBackButton?: boolean hidesBottomTabs?: boolean - // TODO: Remove this once the old infra code gets removed - fullBleed?: boolean - // TODO: Remove this once we the old infra code gets removed - ignoreTabs?: boolean // If this module is the root view of a particular tab, name it here isRootViewForTabName?: BottomTabType // If this module should only be shown in one particular tab, name it here @@ -331,7 +185,6 @@ function defineModules(obj: Record) { } const artQuizScreenOptions = { - fullBleed: true, screenOptions: { gestureEnabled: false, }, @@ -343,7 +196,6 @@ export const modules = defineModules({ Activity: reactModule({ Component: ActivityScreen, options: { - fullBleed: true, hidesBottomTabs: true, screenOptions: { headerShown: false, @@ -353,7 +205,6 @@ export const modules = defineModules({ ActivityItem: reactModule({ Component: ActivityItemScreenQueryRenderer, options: { - fullBleed: true, hidesBottomTabs: true, screenOptions: { headerShown: false, @@ -379,7 +230,6 @@ export const modules = defineModules({ AlertArtworks: reactModule({ Component: AlertArtworks, options: { - fullBleed: true, hidesBottomTabs: true, screenOptions: { headerShown: false, @@ -393,7 +243,6 @@ export const modules = defineModules({ ArtQuizResults: reactModule({ Component: ArtQuizResults, options: { - fullBleed: true, screenOptions: { animationTypeForReplace: "pop", headerShown: false, @@ -403,7 +252,6 @@ export const modules = defineModules({ Article: reactModule({ Component: ArticleScreen, options: { - fullBleed: true, screenOptions: { headerShown: false, }, @@ -412,7 +260,6 @@ export const modules = defineModules({ ArticleSlideShow: reactModule({ Component: ArticlesSlideShowScreen, options: { - fullBleed: true, hidesBottomTabs: true, screenOptions: { headerShown: false, @@ -422,7 +269,6 @@ export const modules = defineModules({ Articles: reactModule({ Component: ArticlesScreen, options: { - fullBleed: true, screenOptions: { headerShown: false, }, @@ -442,7 +288,6 @@ export const modules = defineModules({ ArtistArticles: reactModule({ Component: ArtistArticlesQueryRenderer, options: { - fullBleed: true, screenOptions: { headerShown: false, }, @@ -451,7 +296,6 @@ export const modules = defineModules({ ArtistSeries: reactModule({ Component: ArtistSeriesQueryRenderer, options: { - fullBleed: true, screenOptions: { headerShown: false, }, @@ -469,33 +313,12 @@ export const modules = defineModules({ }), ArtworkMedium: reactModule({ Component: ArtworkMediumQueryRenderer, - options: { - fullBleed: true, - alwaysPresentModally: !unsafe_getFeatureFlag("AREnableNewNavigation"), - modalPresentationStyle: !unsafe_getFeatureFlag("AREnableNewNavigation") - ? "fullScreen" - : undefined, - }, }), ArtworkAttributionClassFAQ: reactModule({ Component: ArtworkAttributionClassFAQQueryRenderer, - options: { - fullBleed: true, - alwaysPresentModally: !unsafe_getFeatureFlag("AREnableNewNavigation"), - modalPresentationStyle: !unsafe_getFeatureFlag("AREnableNewNavigation") - ? "fullScreen" - : undefined, - }, }), ArtworkCertificateAuthenticity: reactModule({ Component: CertificateOfAuthenticity, - options: { - fullBleed: true, - alwaysPresentModally: !unsafe_getFeatureFlag("AREnableNewNavigation"), - modalPresentationStyle: !unsafe_getFeatureFlag("AREnableNewNavigation") - ? "fullScreen" - : undefined, - }, }), ArtworkList: reactModule({ Component: ArtworkListScreen, @@ -515,13 +338,12 @@ export const modules = defineModules({ }), Auction: reactModule({ Component: SaleQueryRenderer, - options: { fullBleed: true, screenOptions: { headerShown: false } }, + options: { screenOptions: { headerShown: false } }, Queries: [SaleScreenQuery], }), Auctions: reactModule({ Component: SalesScreen, options: { - fullBleed: true, screenOptions: { headerShown: false, }, @@ -531,9 +353,6 @@ export const modules = defineModules({ AuctionInfo: reactModule({ Component: SaleInfoQueryRenderer }), AuctionResult: reactModule({ Component: AuctionResultQueryRenderer, - options: { - hidesBackButton: !unsafe_getFeatureFlag("AREnableNewNavigation"), - }, }), AuctionResultsForArtistsYouFollow: reactModule({ Component: AuctionResultsForArtistsYouFollowQueryRenderer, @@ -556,7 +375,6 @@ export const modules = defineModules({ Component: RegistrationFlow, options: { alwaysPresentModally: true, - fullBleed: Platform.OS === "ios" && !unsafe_getFeatureFlag("AREnableNewNavigation"), screenOptions: { // Don't allow the screen to be swiped away by mistake gestureEnabled: false, @@ -568,7 +386,7 @@ export const modules = defineModules({ Component: BidFlow, options: { alwaysPresentModally: true, - fullBleed: !unsafe_getFeatureFlag("AREnableNewNavigation"), + screenOptions: { headerShown: false, }, @@ -576,13 +394,6 @@ export const modules = defineModules({ }), AuctionBuyersPremium: reactModule({ Component: AuctionBuyersPremiumQueryRenderer, - options: { - fullBleed: true, - alwaysPresentModally: !unsafe_getFeatureFlag("AREnableNewNavigation"), - modalPresentationStyle: !unsafe_getFeatureFlag("AREnableNewNavigation") - ? "fullScreen" - : undefined, - }, }), BrowseSimilarWorks: reactModule({ Component: BrowseSimilarWorksQueryRenderer, @@ -596,26 +407,22 @@ export const modules = defineModules({ CareerHighlightsBigCardsSwiper: reactModule({ Component: CareerHighlightsBigCardsSwiper, options: { - alwaysPresentModally: !unsafe_getFeatureFlag("AREnableNewNavigation"), - fullBleed: !unsafe_getFeatureFlag("AREnableNewNavigation"), - hidesBottomTabs: unsafe_getFeatureFlag("AREnableNewNavigation"), + hidesBottomTabs: true, screenOptions: { headerShown: false, }, }, }), - City: reactModule({ Component: CityView, options: { fullBleed: true, ignoreTabs: true } }), - CityFairList: reactModule({ Component: CityFairListQueryRenderer, options: { fullBleed: true } }), + City: reactModule({ Component: CityView }), + CityFairList: reactModule({ Component: CityFairListQueryRenderer }), CityPicker: reactModule({ Component: CityPicker, - options: { fullBleed: true, ignoreTabs: true }, }), CitySavedList: reactModule({ Component: CitySavedListQueryRenderer }), CitySectionList: reactModule({ Component: CitySectionListQueryRenderer }), Collection: reactModule({ Component: CollectionScreen, options: { - fullBleed: true, screenOptions: { headerShown: false, }, @@ -624,7 +431,6 @@ export const modules = defineModules({ CollectionsByCategory: reactModule({ Component: CollectionsByCategory, options: { - fullBleed: true, screenOptions: { headerShown: false, }, @@ -633,14 +439,13 @@ export const modules = defineModules({ ConsignmentInquiry: reactModule({ Component: ConsignmentInquiryScreen, options: { - hidesBottomTabs: !unsafe_getFeatureFlag("AREnableNewNavigation"), screenOptions: { gestureEnabled: false, }, }, }), Conversation: reactModule({ - Component: Conversation, + Component: ConversationQueryRenderer, options: { onlyShowInTabName: "inbox", screenOptions: { @@ -660,11 +465,7 @@ export const modules = defineModules({ DevMenu: reactModule({ Component: DevMenu, options: { - // No need to hide bottom tabs if it's a modal because they will be hidden by default - hidesBottomTabs: !unsafe_getFeatureFlag("AREnableNewNavigation"), - hidesBackButton: !unsafe_getFeatureFlag("AREnableNewNavigation"), - alwaysPresentModally: !!unsafe_getFeatureFlag("AREnableNewNavigation"), - fullBleed: !!unsafe_getFeatureFlag("AREnableNewNavigation"), + alwaysPresentModally: true, screenOptions: { headerTitle: "Dev Settings", headerLargeTitle: true, @@ -686,7 +487,6 @@ export const modules = defineModules({ Fair: reactModule({ Component: FairScreen, options: { - fullBleed: true, screenOptions: { headerShown: false, }, @@ -696,7 +496,6 @@ export const modules = defineModules({ FairMoreInfo: reactModule({ Component: FairMoreInfoQueryRenderer, options: { - fullBleed: true, screenOptions: { headerShown: false, }, @@ -721,13 +520,12 @@ export const modules = defineModules({ Favorites: reactModule({ Component: Favorites, options: { - fullBleed: true, screenOptions: { headerShown: false, }, }, }), - Feature: reactModule({ Component: FeatureQueryRenderer, options: { fullBleed: true } }), + Feature: reactModule({ Component: FeatureQueryRenderer }), FullArtistSeriesList: reactModule({ Component: ArtistSeriesFullArtistSeriesListQueryRenderer, options: { @@ -747,7 +545,6 @@ export const modules = defineModules({ GalleriesForYou: reactModule({ Component: GalleriesForYouScreen, options: { - fullBleed: true, screenOptions: { headerShown: false, }, @@ -756,7 +553,6 @@ export const modules = defineModules({ Gene: reactModule({ Component: GeneQueryRenderer, options: { - fullBleed: true, screenOptions: { headerShown: false, }, @@ -767,7 +563,7 @@ export const modules = defineModules({ options: { isRootViewForTabName: "home", onlyShowInTabName: "home", - fullBleed: true, + screenOptions: { headerShown: false, }, @@ -777,7 +573,6 @@ export const modules = defineModules({ HomeViewSectionScreen: reactModule({ Component: HomeViewSectionScreenQueryRenderer, options: { - fullBleed: true, screenOptions: { headerShown: false, }, @@ -788,7 +583,7 @@ export const modules = defineModules({ options: { isRootViewForTabName: "inbox", onlyShowInTabName: "inbox", - fullBleed: true, + screenOptions: { headerShown: false, }, @@ -796,7 +591,7 @@ export const modules = defineModules({ Queries: [InboxScreenQuery], }), Inquiry: reactModule({ - Component: Inquiry, + Component: InquiryQueryRenderer, options: { alwaysPresentModally: true, screenOptions: { @@ -808,7 +603,6 @@ export const modules = defineModules({ Component: LiveAuctionView, options: { alwaysPresentModally: true, - modalPresentationStyle: "fullScreen", screenOptions: { headerShown: false, }, @@ -817,25 +611,22 @@ export const modules = defineModules({ LocalDiscovery: reactModule({ Component: CityGuideView, options: { - fullBleed: true, - screenOptions: unsafe_getFeatureFlag("AREnableNewNavigation") - ? { - headerTransparent: true, - headerLeft: () => { - return ( - { - goBack() - }} - /> - ) - }, - } - : undefined, + screenOptions: { + headerTransparent: true, + headerLeft: () => { + return ( + { + goBack() + }} + /> + ) + }, + }, }, }), MakeOfferModal: reactModule({ @@ -847,7 +638,7 @@ export const modules = defineModules({ }, }), MedianSalePriceAtAuction: reactModule({ Component: MedianSalePriceAtAuction }), - Map: reactModule({ Component: MapContainer, options: { fullBleed: true, ignoreTabs: true } }), + Map: reactModule({ Component: MapContainer }), MyAccount: reactModule({ Component: MyAccountQueryRenderer, options: { @@ -859,7 +650,6 @@ export const modules = defineModules({ MyAccountEditEmail: reactModule({ Component: MyAccountEditEmailQueryRenderer, options: { - hidesBackButton: !unsafe_getFeatureFlag("AREnableNewNavigation"), screenOptions: { headerTitle: "Email", }, @@ -868,7 +658,6 @@ export const modules = defineModules({ MyAccountEditPriceRange: reactModule({ Component: MyAccountEditPriceRangeQueryRenderer, options: { - hidesBackButton: !unsafe_getFeatureFlag("AREnableNewNavigation"), screenOptions: { headerTitle: "Price Range", }, @@ -877,7 +666,6 @@ export const modules = defineModules({ MyAccountEditPassword: reactModule({ Component: MyAccountEditPassword, options: { - hidesBackButton: !unsafe_getFeatureFlag("AREnableNewNavigation"), screenOptions: { headerTitle: "Password", }, @@ -886,7 +674,6 @@ export const modules = defineModules({ MyAccountEditPhone: reactModule({ Component: MyAccountEditPhoneQueryRenderer, options: { - hidesBackButton: !unsafe_getFeatureFlag("AREnableNewNavigation"), screenOptions: { headerTitle: "Phone Number", }, @@ -898,7 +685,6 @@ export const modules = defineModules({ MyCollectionArtwork: reactModule({ Component: MyCollectionArtworkScreen, options: { - fullBleed: true, screenOptions: { headerShown: false, }, @@ -908,9 +694,8 @@ export const modules = defineModules({ MyCollectionArtworkAdd: reactModule({ Component: MyCollectionArtworkAdd, options: { - hidesBottomTabs: !unsafe_getFeatureFlag("AREnableNewNavigation"), alwaysPresentModally: true, - modalPresentationStyle: "fullScreen", + screenOptions: { gestureEnabled: false, headerShown: false, @@ -920,9 +705,8 @@ export const modules = defineModules({ MyCollectionArtworkEdit: reactModule({ Component: MyCollectionArtworkEditQueryRenderer, options: { - hidesBottomTabs: !unsafe_getFeatureFlag("AREnableNewNavigation"), alwaysPresentModally: true, - modalPresentationStyle: "fullScreen", + screenOptions: { gestureEnabled: false, headerShown: false, @@ -932,7 +716,6 @@ export const modules = defineModules({ MyCollectionAddCollectedArtists: reactModule({ Component: MyCollectionAddCollectedArtistsScreen, options: { - hidesBackButton: !unsafe_getFeatureFlag("AREnableNewNavigation"), hidesBottomTabs: true, screenOptions: { headerTitle: "Add Artists You Collect", @@ -957,7 +740,7 @@ export const modules = defineModules({ options: { isRootViewForTabName: "profile", onlyShowInTabName: "profile", - fullBleed: true, + screenOptions: { headerShown: false, }, @@ -967,7 +750,6 @@ export const modules = defineModules({ CompleteMyProfile: reactModule({ Component: CompleteMyProfile, options: { - fullBleed: true, hidesBottomTabs: true, screenOptions: { headerShown: false, @@ -1003,7 +785,7 @@ export const modules = defineModules({ Component: NewWorksForYouQueryRenderer, options: { hidesBottomTabs: true, - fullBleed: true, + screenOptions: { headerShown: false, }, @@ -1028,7 +810,6 @@ export const modules = defineModules({ NewWorksFromGalleriesYouFollow: reactModule({ Component: NewWorksFromGalleriesYouFollowScreen, options: { - fullBleed: true, screenOptions: { headerShown: false, }, @@ -1037,7 +818,6 @@ export const modules = defineModules({ News: reactModule({ Component: NewsScreen, options: { - fullBleed: true, screenOptions: { headerShown: false, }, @@ -1063,13 +843,12 @@ export const modules = defineModules({ Partner: reactModule({ Component: PartnerQueryRenderer, options: { - fullBleed: true, screenOptions: { headerShown: false, }, }, }), - PartnerLocations: reactModule({ Component: PartnerLocations }), + PartnerLocations: reactModule({ Component: PartnerLocationsQueryRenderer }), PartnerOfferContainer: reactModule({ Component: PartnerOfferContainer, options: { @@ -1107,9 +886,7 @@ export const modules = defineModules({ Component: ArtsyWebViewPage, options: { alwaysPresentModally: true, - modalPresentationStyle: !unsafe_getFeatureFlag("AREnableNewNavigation") - ? "fullScreen" - : undefined, + screenOptions: { gestureEnabled: false, headerShown: false, @@ -1119,7 +896,6 @@ export const modules = defineModules({ ReactWebView: reactModule({ Component: ArtsyWebViewPage, options: { - fullBleed: !unsafe_getFeatureFlag("AREnableNewNavigation"), screenOptions: { headerShown: false, }, @@ -1137,7 +913,6 @@ export const modules = defineModules({ RecentlyViewed: reactModule({ Component: RecentlyViewedScreen, options: { - fullBleed: true, screenOptions: { headerShown: false, }, @@ -1148,7 +923,7 @@ export const modules = defineModules({ Component: RecommendedAuctionLotsQueryRenderer, options: { hidesBottomTabs: true, - fullBleed: true, + screenOptions: { headerShown: false, }, @@ -1159,7 +934,7 @@ export const modules = defineModules({ options: { isRootViewForTabName: "sell", onlyShowInTabName: "sell", - fullBleed: true, + screenOptions: { headerShown: false, }, @@ -1170,7 +945,6 @@ export const modules = defineModules({ SavedArtworks: reactModule({ Component: SavedArtworks, options: { - fullBleed: true, screenOptions: { headerShown: false, }, @@ -1179,7 +953,6 @@ export const modules = defineModules({ SavedSearchAlertsList: reactModule({ Component: SavedSearchAlertsListQueryRenderer, options: { - fullBleed: true, screenOptions: { headerShown: false, }, @@ -1190,19 +963,18 @@ export const modules = defineModules({ options: { isRootViewForTabName: "search", onlyShowInTabName: "search", - fullBleed: true, + screenOptions: { headerShown: false, }, }, Queries: [SearchScreenQuery], }), - Show: reactModule({ Component: ShowQueryRenderer, options: { fullBleed: true } }), + Show: reactModule({ Component: ShowQueryRenderer }), ShowMoreInfo: reactModule({ Component: ShowMoreInfoQueryRenderer }), SimilarToRecentlyViewed: reactModule({ Component: SimilarToRecentlyViewedScreen, options: { - fullBleed: true, screenOptions: { headerShown: false, }, @@ -1212,9 +984,7 @@ export const modules = defineModules({ Component: SubmitArtworkForm, options: { alwaysPresentModally: true, - modalPresentationStyle: !unsafe_getFeatureFlag("AREnableNewNavigation") - ? "fullScreen" - : undefined, + screenOptions: { gestureEnabled: false, headerShown: false, @@ -1235,7 +1005,6 @@ export const modules = defineModules({ Tag: reactModule({ Component: TagQueryRenderer, options: { - fullBleed: true, screenOptions: { headerShown: false, }, @@ -1251,11 +1020,10 @@ export const modules = defineModules({ }), VanityURLEntity: reactModule({ Component: VanityURLEntityRenderer, - options: { fullBleed: true }, }), ViewingRoom: reactModule({ Component: ViewingRoomQueryRenderer, - options: { fullBleed: true }, + Queries: [ViewingRoomScreenQuery], }), ViewingRoomArtwork: reactModule({ Component: ViewingRoomArtworkScreen }), @@ -1274,15 +1042,3 @@ export const modules = defineModules({ Queries: [WorksForYouScreenQuery], }), }) - -for (const moduleName of Object.keys(modules)) { - const descriptor = modules[moduleName as AppModule] - if (Platform.OS === "ios" && !unsafe_getFeatureFlag("AREnableNewNavigation")) { - // TODO: this should not be needed. right? - register(moduleName, descriptor.Component, { - fullBleed: descriptor.options.fullBleed, - ignoreTabs: descriptor.options.ignoreTabs, - moduleName, - }) - } -} diff --git a/src/app/Components/Artist/ArtistAbout/ArtistAbout.tests.tsx b/src/app/Components/Artist/ArtistAbout/ArtistAbout.tests.tsx index 21957838690..55aed515644 100644 --- a/src/app/Components/Artist/ArtistAbout/ArtistAbout.tests.tsx +++ b/src/app/Components/Artist/ArtistAbout/ArtistAbout.tests.tsx @@ -1,7 +1,6 @@ import { screen } from "@testing-library/react-native" import { ArtistAboutTestsQuery } from "__generated__/ArtistAboutTestsQuery.graphql" import { Biography } from "app/Components/Artist/Biography" -import { ModalStack } from "app/system/navigation/ModalStack" import { setupTestWrapper } from "app/utils/tests/setupTestWrapper" import { graphql } from "react-relay" import { ArtistAboutContainer } from "./ArtistAbout" @@ -9,11 +8,7 @@ import { ArtistAboutShowsFragmentContainer } from "./ArtistAboutShows" describe("ArtistAbout", () => { const { renderWithRelay } = setupTestWrapper({ - Component: ({ artist }) => ( - - - - ), + Component: ({ artist }) => , query: graphql` query ArtistAboutTestsQuery($artistID: String!) @relay_test_operation { artist(id: $artistID) { diff --git a/src/app/Components/ArtsyWebView.tsx b/src/app/Components/ArtsyWebView.tsx index eeff8729371..face69b1111 100644 --- a/src/app/Components/ArtsyWebView.tsx +++ b/src/app/Components/ArtsyWebView.tsx @@ -10,14 +10,13 @@ import { ArtsyKeyboardAvoidingView } from "app/utils/ArtsyKeyboardAvoidingView" import { useBackHandler } from "app/utils/hooks/useBackHandler" import { useDevToggle } from "app/utils/hooks/useDevToggle" import { useEnvironment } from "app/utils/hooks/useEnvironment" -import { useFeatureFlag } from "app/utils/hooks/useFeatureFlag" import { Schema } from "app/utils/track" import { useWebViewCallback } from "app/utils/useWebViewEvent" import { debounce } from "lodash" import { parse as parseQueryString } from "query-string" import { forwardRef, useEffect, useImperativeHandle, useRef, useState } from "react" -import { Platform, View } from "react-native" -import { Edge, SafeAreaView, useSafeAreaInsets } from "react-native-safe-area-context" +import { Platform } from "react-native" +import { Edge } from "react-native-safe-area-context" import Share from "react-native-share" import WebView, { WebViewNavigation, WebViewProps } from "react-native-webview" import { useTracking } from "react-tracking" @@ -69,9 +68,6 @@ export const ArtsyWebViewPage = ({ systemBackAction?: () => void backAction?: () => void } & ArtsyWebViewConfig) => { - const saInsets = useSafeAreaInsets() - const enableNewNavigation = useFeatureFlag("AREnableNewNavigation") - const [canGoBack, setCanGoBack] = useState(false) const webURL = useEnvironment().webURL const ref = useRef(null) @@ -134,11 +130,7 @@ export const ArtsyWebViewPage = ({ return ( - + ( ( - { - url, - onNavigationStateChange: onNavigationStateChangeProp, - isPresentedModally = false, - safeAreaEdges = [], - }, + { url, onNavigationStateChange: onNavigationStateChangeProp, isPresentedModally = false }, ref ) => { - const enableNewNavigation = useFeatureFlag("AREnableNewNavigation") - const innerRef = useRef(null) useImperativeHandle(ref, () => innerRef.current as WebViewWithShareTitleUrl) const userAgent = getCurrentEmissionState().userAgent @@ -268,10 +253,8 @@ export const ArtsyWebView = forwardRef< } } - const WebViewWrapper = isPresentedModally && !enableNewNavigation ? SafeAreaView : View - return ( - + webview )} - + ) } ) diff --git a/src/app/Components/AutosuggestResults/AutosuggestResults.tests.tsx b/src/app/Components/AutosuggestResults/AutosuggestResults.tests.tsx index 166d0439221..49f968ab89b 100644 --- a/src/app/Components/AutosuggestResults/AutosuggestResults.tests.tsx +++ b/src/app/Components/AutosuggestResults/AutosuggestResults.tests.tsx @@ -4,7 +4,6 @@ import { InfiniteScrollFlashList } from "app/Components/InfiniteScrollFlashList" import Spinner from "app/Components/Spinner" import { SearchContext } from "app/Scenes/Search/SearchContext" import { AutosuggestSearchResult } from "app/Scenes/Search/components/AutosuggestSearchResult" -import { __globalStoreTestUtils__ } from "app/store/GlobalStore" import { getMockRelayEnvironment } from "app/system/relay/defaultEnvironment" import { CatchErrors } from "app/utils/CatchErrors" import { extractText } from "app/utils/tests/extractText" @@ -153,7 +152,6 @@ describe("AutosuggestResults", () => { consoleErrorMock.mockClear() notifyRecentSearchMock.mockClear() inputBlurMock.mockClear() - __globalStoreTestUtils__?.injectFeatureFlags({ AREnableNewNavigation: true }) }) afterEach(() => { diff --git a/src/app/Components/Containers/BidFlow.tsx b/src/app/Components/Containers/BidFlow.tsx index 98d9cfcd28e..4c119a5ab8d 100644 --- a/src/app/Components/Containers/BidFlow.tsx +++ b/src/app/Components/Containers/BidFlow.tsx @@ -1,29 +1,18 @@ -import { Screen } from "@artsy/palette-mobile" +import { Flex, Screen } from "@artsy/palette-mobile" import { TimeOffsetProvider } from "app/Components/Bidding/Context/TimeOffsetProvider" import { SelectMaxBidQueryRenderer } from "app/Components/Bidding/Screens/SelectMaxBid" import NavigatorIOS from "app/utils/__legacy_do_not_use__navigator-ios-shim" -import { useFeatureFlag } from "app/utils/hooks/useFeatureFlag" -import { Platform, View } from "react-native" -import { useSafeAreaInsets } from "react-native-safe-area-context" export const BidFlow: React.FC< Omit, "navigator"> > = (props) => { - const insets = useSafeAreaInsets() - const enableNewNavigation = useFeatureFlag("AREnableNewNavigation") - return ( - + - + ) } diff --git a/src/app/Components/Containers/Inquiry.tsx b/src/app/Components/Containers/Inquiry.tsx index 9e4fcf4993d..1741f3610df 100644 --- a/src/app/Components/Containers/Inquiry.tsx +++ b/src/app/Components/Containers/Inquiry.tsx @@ -1,4 +1,4 @@ -import { Spacer, Box, Separator, Button } from "@artsy/palette-mobile" +import { Box, Button, Separator, Spacer } from "@artsy/palette-mobile" import { themeGet } from "@styled-system/theme-get" import { InquiryQuery } from "__generated__/InquiryQuery.graphql" import { Inquiry_artwork$data } from "__generated__/Inquiry_artwork.graphql" @@ -9,7 +9,7 @@ import { dismissModal } from "app/system/navigation/navigate" import { getRelayEnvironment } from "app/system/relay/defaultEnvironment" import { ArtsyKeyboardAvoidingView } from "app/utils/ArtsyKeyboardAvoidingView" import renderWithLoadProgress from "app/utils/renderWithLoadProgress" -import { Schema, Track, track as _track } from "app/utils/track" +import { track as _track, ProvideScreenTracking, Schema, Track } from "app/utils/track" import React from "react" import { View } from "react-native" import { isTablet } from "react-native-device-info" @@ -277,19 +277,27 @@ export const InquiryFragmentContainer = createFragmentContainer(Inquiry, { export const InquiryQueryRenderer: React.FC<{ artworkID: string }> = ({ artworkID }) => { return ( - - environment={getRelayEnvironment()} - query={graphql` - query InquiryQuery($artworkID: String!) { - artwork(id: $artworkID) { - ...Inquiry_artwork - } - } - `} - variables={{ - artworkID, + + > + + environment={getRelayEnvironment()} + query={graphql` + query InquiryQuery($artworkID: String!) { + artwork(id: $artworkID) { + ...Inquiry_artwork + } + } + `} + variables={{ + artworkID, + }} + render={renderWithLoadProgress(InquiryFragmentContainer)} + /> + ) } diff --git a/src/app/Components/LoadFailureView.tsx b/src/app/Components/LoadFailureView.tsx index 74d0d9406b0..48f896915b5 100644 --- a/src/app/Components/LoadFailureView.tsx +++ b/src/app/Components/LoadFailureView.tsx @@ -1,16 +1,16 @@ import { - ReloadIcon, - Flex, + BackButton, Box, BoxProps, - useColor, + DEFAULT_HIT_SLOP, + Flex, + ReloadIcon, Text, Touchable, - BackButton, - DEFAULT_HIT_SLOP, + useColor, } from "@artsy/palette-mobile" import * as Sentry from "@sentry/react-native" -import { __unsafe_mainModalStackRef } from "app/NativeModules/ARScreenPresenterModule" +import { internal_navigationRef } from "app/Navigation/Navigation" import { GlobalStore } from "app/store/GlobalStore" import { goBack } from "app/system/navigation/navigate" import { useDevToggle } from "app/utils/hooks/useDevToggle" @@ -82,10 +82,10 @@ export const LoadFailureView: React.FC = ({ } useEffect(() => { - const routeParams = __unsafe_mainModalStackRef?.current?.getCurrentRoute()?.params + const routeParams = internal_navigationRef?.current?.getCurrentRoute()?.params trackLoadFailureView(error, routeParams) - }, [error, __unsafe_mainModalStackRef?.current?.getCurrentRoute()?.params]) + }, [error, internal_navigationRef?.current?.getCurrentRoute()?.params]) const playAnimation = () => { setIsAnimating(true) diff --git a/src/app/Components/ProgressiveOnboarding/ProgressiveOnboardingAlertFilters.tests.tsx b/src/app/Components/ProgressiveOnboarding/ProgressiveOnboardingAlertFilters.tests.tsx index 2511c60dafe..22d3a40df91 100644 --- a/src/app/Components/ProgressiveOnboarding/ProgressiveOnboardingAlertFilters.tests.tsx +++ b/src/app/Components/ProgressiveOnboarding/ProgressiveOnboardingAlertFilters.tests.tsx @@ -19,6 +19,7 @@ const mockAddListener = jest.fn((event, callback) => { }) jest.mock("@react-navigation/native", () => ({ + ...jest.requireActual("@react-navigation/native"), useNavigation: () => ({ addListener: mockAddListener, navigate: jest.fn(), diff --git a/src/app/Components/ProgressiveOnboarding/ProgressiveOnboardingFindSavedArtwork.tests.tsx b/src/app/Components/ProgressiveOnboarding/ProgressiveOnboardingFindSavedArtwork.tests.tsx index b9efac9afb9..8ce683e6e73 100644 --- a/src/app/Components/ProgressiveOnboarding/ProgressiveOnboardingFindSavedArtwork.tests.tsx +++ b/src/app/Components/ProgressiveOnboarding/ProgressiveOnboardingFindSavedArtwork.tests.tsx @@ -21,6 +21,7 @@ const mockAddListener = jest.fn((event, callback) => { }) jest.mock("@react-navigation/native", () => ({ + ...jest.requireActual("@react-navigation/native"), useNavigation: () => ({ addListener: mockAddListener, navigate: jest.fn(), diff --git a/src/app/Components/ProgressiveOnboarding/ProgressiveOnboardingOfferSettings.tests.tsx b/src/app/Components/ProgressiveOnboarding/ProgressiveOnboardingOfferSettings.tests.tsx index 9b5bd08af2d..a46fa48a24a 100644 --- a/src/app/Components/ProgressiveOnboarding/ProgressiveOnboardingOfferSettings.tests.tsx +++ b/src/app/Components/ProgressiveOnboarding/ProgressiveOnboardingOfferSettings.tests.tsx @@ -24,6 +24,7 @@ const mockAddListener = jest.fn((event, callback) => { }) jest.mock("@react-navigation/native", () => ({ + ...jest.requireActual("@react-navigation/native"), useNavigation: () => ({ addListener: mockAddListener, navigate: jest.fn(), diff --git a/src/app/Components/ProgressiveOnboarding/ProgressiveOnboardingSaveAlert.tests.tsx b/src/app/Components/ProgressiveOnboarding/ProgressiveOnboardingSaveAlert.tests.tsx index aa180f6d96e..f1ed9478e60 100644 --- a/src/app/Components/ProgressiveOnboarding/ProgressiveOnboardingSaveAlert.tests.tsx +++ b/src/app/Components/ProgressiveOnboarding/ProgressiveOnboardingSaveAlert.tests.tsx @@ -19,6 +19,7 @@ const mockAddListener = jest.fn((event, callback) => { }) jest.mock("@react-navigation/native", () => ({ + ...jest.requireActual("@react-navigation/native"), useNavigation: () => ({ addListener: mockAddListener, navigate: jest.fn(), diff --git a/src/app/Components/ProgressiveOnboarding/ProgressiveOnboardingSaveArtwork.tests.tsx b/src/app/Components/ProgressiveOnboarding/ProgressiveOnboardingSaveArtwork.tests.tsx index 5c85c813df3..c99bd5c98e9 100644 --- a/src/app/Components/ProgressiveOnboarding/ProgressiveOnboardingSaveArtwork.tests.tsx +++ b/src/app/Components/ProgressiveOnboarding/ProgressiveOnboardingSaveArtwork.tests.tsx @@ -25,6 +25,7 @@ const mockAddListener = jest.fn((event, callback) => { }) jest.mock("@react-navigation/native", () => ({ + ...jest.requireActual("@react-navigation/native"), useNavigation: () => ({ addListener: mockAddListener, navigate: jest.fn(), diff --git a/src/app/Components/ProgressiveOnboarding/ProgressiveOnboardingSignalInterest.tests.tsx b/src/app/Components/ProgressiveOnboarding/ProgressiveOnboardingSignalInterest.tests.tsx index 43781cc8836..8b55f784461 100644 --- a/src/app/Components/ProgressiveOnboarding/ProgressiveOnboardingSignalInterest.tests.tsx +++ b/src/app/Components/ProgressiveOnboarding/ProgressiveOnboardingSignalInterest.tests.tsx @@ -23,6 +23,7 @@ const mockAddListener = jest.fn((event, callback) => { const mockUseIsFocusedMock = jest.fn() jest.mock("@react-navigation/native", () => ({ + ...jest.requireActual("@react-navigation/native"), useNavigation: () => ({ addListener: mockAddListener, navigate: jest.fn(), diff --git a/src/app/Components/ProgressiveOnboarding/useDismissSavedArtwork.tests.tsx b/src/app/Components/ProgressiveOnboarding/useDismissSavedArtwork.tests.tsx index 7f74fcd1844..fa614cfee66 100644 --- a/src/app/Components/ProgressiveOnboarding/useDismissSavedArtwork.tests.tsx +++ b/src/app/Components/ProgressiveOnboarding/useDismissSavedArtwork.tests.tsx @@ -4,6 +4,7 @@ import { useDismissSavedArtwork } from "./useDismissSavedArtwork" const mockUseIsFocusedMock = jest.fn() jest.mock("@react-navigation/native", () => ({ + ...jest.requireActual("@react-navigation/native"), useIsFocused: () => mockUseIsFocusedMock(), })) diff --git a/src/app/Components/Toast/ToastComponent.tsx b/src/app/Components/Toast/ToastComponent.tsx index 98c260c3622..bd90a78d3e5 100644 --- a/src/app/Components/Toast/ToastComponent.tsx +++ b/src/app/Components/Toast/ToastComponent.tsx @@ -1,7 +1,7 @@ import { Box, Flex, Text, Touchable, useColor } from "@artsy/palette-mobile" import { useActionSheet } from "@expo/react-native-action-sheet" import { OpaqueImageView } from "app/Components/OpaqueImageView2" -import { __unsafe_mainModalStackRef } from "app/NativeModules/ARScreenPresenterModule" +import { internal_navigationRef } from "app/Navigation/Navigation" import { GlobalStore } from "app/store/GlobalStore" import { useScreenDimensions } from "app/utils/hooks" import { useEffect, useMemo, useState } from "react" @@ -69,8 +69,8 @@ export const ToastComponent = ({ const { modules } = require("app/AppRegistry") - const moduleName = __unsafe_mainModalStackRef?.current?.getCurrentRoute()?.params // @ts-expect-error - ?.moduleName as keyof typeof modules + const moduleName = internal_navigationRef?.current?.getCurrentRoute() + ?.name as keyof typeof modules const isBottomTabHidden = modules[moduleName]?.options?.hidesBottomTabs diff --git a/src/app/NativeModules/ARScreenPresenterModule.tsx b/src/app/NativeModules/ARScreenPresenterModule.tsx deleted file mode 100644 index 1616df56975..00000000000 --- a/src/app/NativeModules/ARScreenPresenterModule.tsx +++ /dev/null @@ -1,173 +0,0 @@ -import { - NavigationAction, - NavigationContainerRef, - NavigationState, - StackActions, - TabActions, -} from "@react-navigation/native" -import { BottomTabType } from "app/Scenes/BottomTabs/BottomTabType" -import { ViewDescriptor } from "app/system/navigation/navigate" -import { scrollTabToTop } from "app/utils/bottomTabsHelper" -import immer from "immer" -import { last } from "lodash" -import { NativeModules, StatusBar } from "react-native" -/** - * Here we maintain references to all the navigators in the main app navigation hierarchy, which are: - * - tab nav stacks - * i.e. what you see whe you switch to a particular tab - * - the main modal stack - * i.e. the place where global modals are presented (excluding FancyModal) - * - modal nav stacks - * i.e. the navigation stack _within_ a presented modal. - * These are unique in that they are created and destroyed, while all the others are only created once - */ - -export const __unsafe_mainModalStackRef = { current: null as NavigationContainerRef | null } - -type Mutable = T extends object - ? { - -readonly [P in keyof T]: Mutable - } - : T extends Array - ? Array> - : T extends ReadonlyArray - ? Array> - : T - -function updateNavigationState(updater: (draft: Mutable) => void) { - const currentState = __unsafe_mainModalStackRef?.current?.getRootState() - if (currentState) { - const nextState = immer(currentState, updater) - __unsafe_mainModalStackRef?.current?.resetRoot(nextState) - } -} -function updateTabStackState( - tab: BottomTabType, - updater: (draft: Mutable) => void -) { - updateNavigationState((state) => { - if (!state) { - return - } - const tabs = state.routes[0].state?.routes - const tabState = ( - tabs as Array<{ name: BottomTabType; state: Mutable }> - )?.find((x) => x.name === tab)?.state - if (!tabState) { - console.error("unable to find tab state for tab", tab, state) - return - } - updater(tabState) - }) -} - -// If the user is looking at a modal, return the nav stack ref for that modal, otherwise return null. -function getCurrentlyPresentedModalNavStackKey() { - const mainModalStackRoutes = __unsafe_mainModalStackRef?.current?.getRootState()?.routes - - if (!mainModalStackRoutes || mainModalStackRoutes.length <= 1) { - // the user is not looking at a modal. - return null - } - - const key = last(mainModalStackRoutes)?.key - if (!key) { - throw new Error("Couldn't get modal key") - } - - return key -} - -// When coming from a killed state our nav stack may not be -// set up yet, we check and wait for animations to finish -// to more reliably navigate -function dispatchNavAction(action: NavigationAction) { - if (!__unsafe_mainModalStackRef?.current) { - requestAnimationFrame(() => { - __unsafe_mainModalStackRef?.current?.dispatch(action) - }) - } else { - __unsafe_mainModalStackRef?.current?.dispatch(action) - } -} - -export const ARScreenPresenterModule: (typeof NativeModules)["ARScreenPresenterModule"] = { - switchTab(tab: BottomTabType) { - dispatchNavAction(TabActions.jumpTo(tab)) - }, - presentModal(viewDescriptor: ViewDescriptor) { - if (viewDescriptor.replaceActiveModal) { - dispatchNavAction( - StackActions.replace("modal", { - rootModuleName: viewDescriptor.moduleName, - rootModuleProps: viewDescriptor.props, - }) - ) - } else { - dispatchNavAction( - StackActions.push("modal", { - rootModuleName: viewDescriptor.moduleName, - rootModuleProps: viewDescriptor.props, - }) - ) - } - }, - async popToRootAndScrollToTop(selectedTab: BottomTabType) { - updateTabStackState(selectedTab, (state) => { - state.routes = [state.routes[0]] - state.index = 0 - }) - - scrollTabToTop(selectedTab) - }, - popToRootOrScrollToTop(selectedTab: BottomTabType) { - updateTabStackState(selectedTab, (state) => { - if (state.routes.length > 1) { - state.routes = [state.routes[0]] - state.index = 0 - } else { - scrollTabToTop(selectedTab) - } - }) - }, - pushView(selectedTab: BottomTabType, viewDescriptor: ViewDescriptor) { - const stackKey = getCurrentlyPresentedModalNavStackKey() ?? selectedTab - if (viewDescriptor.replaceActiveScreen) { - dispatchNavAction( - StackActions.replace("screen:" + stackKey, { - moduleName: viewDescriptor.moduleName, - props: viewDescriptor.props, - }) - ) - } else { - dispatchNavAction( - StackActions.push("screen:" + stackKey, { - moduleName: viewDescriptor.moduleName, - props: viewDescriptor.props, - }) - ) - } - }, - popStack(selectedTab: BottomTabType) { - updateTabStackState(selectedTab, (state) => { - state.routes.pop() - state.index -= 1 - }) - }, - goBack(_selectedTab: BottomTabType) { - __unsafe_mainModalStackRef?.current?.goBack() - }, - dismissModal(..._args: any[]) { - StatusBar.setBarStyle("dark-content", true) - updateNavigationState((state) => { - if (state.routes.length === 1) { - return - } - state.routes.pop() - state.index -= 1 - }) - }, - updateShouldHideBackButton: () => { - console.warn("updateShouldHideBackButton not yet supported") - }, -} diff --git a/src/app/NativeModules/LegacyNativeModules.tsx b/src/app/NativeModules/LegacyNativeModules.tsx index beed3c6f380..a68c4d1f2ac 100644 --- a/src/app/NativeModules/LegacyNativeModules.tsx +++ b/src/app/NativeModules/LegacyNativeModules.tsx @@ -1,11 +1,8 @@ import AsyncStorage from "@react-native-async-storage/async-storage" -import { BottomTabType } from "app/Scenes/BottomTabs/BottomTabType" import { NativeState } from "app/store/NativeModel" import { PushAuthorizationStatus } from "app/utils/PushNotification" import { NativeModules as AllNativeModules, Platform } from "react-native" import { getLocales, getTimeZone } from "react-native-localize" -import { ARScreenPresenterModule } from "./ARScreenPresenterModule" -import type { ViewDescriptor } from "app/system/navigation/navigate" import type { Image as RNCImage } from "react-native-image-crop-picker" const noop: any = (name: string) => () => @@ -75,17 +72,6 @@ interface LegacyNativeModules { cacheKey: string ): void } - ARScreenPresenterModule: { - switchTab(tab: BottomTabType): void - pushView(currentTabStackID: string, descriptor: ViewDescriptor): void - presentModal(descriptor: ViewDescriptor): void - dismissModal(): void - goBack(currentTabStackID: string): void - popStack(stackID: string): void - popToRootOrScrollToTop(stackID: string): void - popToRootAndScrollToTop(stackID: string): Promise - updateShouldHideBackButton(shouldHideBackButton: boolean, currentTabStackID: string): void - } ARTDeeplinkTimeoutModule: { invalidateDeeplinkTimeout(): void } @@ -145,14 +131,12 @@ const LegacyNativeModulesAndroid = { ARPHPhotoPickerModule: { requestPhotos: noop("requestPhotos"), }, - ARScreenPresenterModule, AREventsModule: { requestAppStoreRating: noop("requestAppStoreRating"), }, } const LegacyNativeModulesIOS: LegacyNativeModules = { - ARScreenPresenterModule, ARTDeeplinkTimeoutModule: AllNativeModules.ARTDeeplinkTimeoutModule, ARTNativeScreenPresenterModule: AllNativeModules.ARTNativeScreenPresenterModule, ARCocoaConstantsModule: AllNativeModules.ARCocoaConstantsModule, diff --git a/src/app/Navigation/AuthenticatedRoutes/StackNavigator.tsx b/src/app/Navigation/AuthenticatedRoutes/StackNavigator.tsx index 28fc7df3645..dcd75d966c8 100644 --- a/src/app/Navigation/AuthenticatedRoutes/StackNavigator.tsx +++ b/src/app/Navigation/AuthenticatedRoutes/StackNavigator.tsx @@ -10,7 +10,6 @@ import { useBottomTabBarHeight } from "@react-navigation/bottom-tabs" import { createNativeStackNavigator } from "@react-navigation/native-stack" import { ModuleDescriptor } from "app/AppRegistry" import { AuthenticatedRoutesParams } from "app/Navigation/AuthenticatedRoutes/Tabs" -import { isHeaderShown } from "app/Navigation/Utils/isHeaderShown" import { isModalScreen } from "app/Navigation/Utils/isModalScreen" import { goBack } from "app/system/navigation/navigate" import { Platform } from "react-native" @@ -30,8 +29,6 @@ export const registerScreen: React.FC = ({ name, modu name={name} key={name} options={{ - presentation: isModalScreen(module) ? "fullScreenModal" : "card", - headerShown: isHeaderShown(module), orientation: !isTablet() ? "portrait" : "default", headerLeft: ({ canGoBack }) => { if (!canGoBack) { diff --git a/src/app/Navigation/Utils/isHeaderShown.tsx b/src/app/Navigation/Utils/isHeaderShown.tsx deleted file mode 100644 index b8c6c1697b4..00000000000 --- a/src/app/Navigation/Utils/isHeaderShown.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import { ModuleDescriptor } from "app/AppRegistry" - -export const isHeaderShown = (module: ModuleDescriptor) => { - return !module.options.hidesBackButton && !module.options.hasOwnModalCloseButton -} diff --git a/src/app/Providers.tsx b/src/app/Providers.tsx index 30e94a972a0..836c5713562 100644 --- a/src/app/Providers.tsx +++ b/src/app/Providers.tsx @@ -1,4 +1,4 @@ -import { Theme, Spinner, ScreenDimensionsProvider, Screen } from "@artsy/palette-mobile" +import { Screen, ScreenDimensionsProvider, Spinner, Theme } from "@artsy/palette-mobile" import { ActionSheetProvider } from "@expo/react-native-action-sheet" import { PortalProvider } from "@gorhom/portal" import { ArtworkListsProvider } from "app/Components/ArtworkLists/ArtworkListsContext" @@ -6,6 +6,7 @@ import { ShareSheetProvider } from "app/Components/ShareSheet/ShareSheetContext" import { getRelayEnvironment } from "app/system/relay/defaultEnvironment" import { useFeatureFlag } from "app/utils/hooks/useFeatureFlag" import { ProvideScreenDimensions } from "app/utils/hooks/useScreenDimensions" +import { NavigationTestsProvider } from "app/utils/tests/NavigationTestsProvider" import { Component, Suspense } from "react" import { GestureHandlerRootView } from "react-native-gesture-handler" import { SafeAreaProvider } from "react-native-safe-area-context" @@ -50,12 +51,14 @@ export const Providers: React.FC<{ children: React.ReactNode }> = ({ children }) children ) -export const TestProviders: React.FC<{ skipRelay?: boolean }> = ({ +export const TestProviders: React.FC<{ skipRelay?: boolean; includeNavigation?: boolean }> = ({ children, skipRelay = false, + includeNavigation = false, }) => { return combineProviders( [ + includeNavigation && NavigationTestsProvider, TrackingProvider, GlobalStoreProvider, SafeAreaProvider, diff --git a/src/app/Scenes/About/About.tsx b/src/app/Scenes/About/About.tsx index f193181c4b4..314299503b0 100644 --- a/src/app/Scenes/About/About.tsx +++ b/src/app/Scenes/About/About.tsx @@ -1,17 +1,14 @@ import { useTheme } from "@artsy/palette-mobile" import { MenuItem } from "app/Components/MenuItem" -import { PageWithSimpleHeader } from "app/Components/PageWithSimpleHeader" import { useToast } from "app/Components/Toast/toastHook" import { GlobalStore } from "app/store/GlobalStore" import { navigate } from "app/system/navigation/navigate" -import { useFeatureFlag } from "app/utils/hooks/useFeatureFlag" -import React, { Fragment, useEffect, useState } from "react" +import React, { useEffect, useState } from "react" import { ScrollView } from "react-native" import DeviceInfo from "react-native-device-info" import useDebounce from "react-use/lib/useDebounce" export const About: React.FC = () => { - const enableNewNavigation = useFeatureFlag("AREnableNewNavigation") const { color } = useTheme() const appVersion = DeviceInfo.getVersion() const toast = useToast() @@ -44,28 +41,20 @@ export const About: React.FC = () => { [tapCount] ) - const Wrapper = enableNewNavigation - ? Fragment - : ({ children }: { children: React.ReactNode }) => ( - {children} - ) - return ( - - - navigate("/terms")} /> - navigate("/privacy")} /> - navigate("/supplemental-cos")} /> - updateTapCount((count) => count + 1)} - chevron={false} - style={ - userIsDev ? { borderRightColor: color("devpurple"), borderRightWidth: 1 } : undefined - } - /> - - + + navigate("/terms")} /> + navigate("/privacy")} /> + navigate("/supplemental-cos")} /> + updateTapCount((count) => count + 1)} + chevron={false} + style={ + userIsDev ? { borderRightColor: color("devpurple"), borderRightWidth: 1 } : undefined + } + /> + ) } diff --git a/src/app/Scenes/Artist/Artist.tests.tsx b/src/app/Scenes/Artist/Artist.tests.tsx index ab6abb91471..16fef51dda9 100644 --- a/src/app/Scenes/Artist/Artist.tests.tsx +++ b/src/app/Scenes/Artist/Artist.tests.tsx @@ -1,5 +1,5 @@ import { fireEvent, screen } from "@testing-library/react-native" -import { ModalStack } from "app/system/navigation/ModalStack" +import { getRelayEnvironment } from "app/system/relay/defaultEnvironment" import { flushPromiseQueue } from "app/utils/tests/flushPromiseQueue" import { renderWithHookWrappersTL } from "app/utils/tests/renderWithWrappers" import { postEventToProviders } from "app/utils/track/providers" @@ -44,13 +44,11 @@ describe("Artist", () => { } const TestWrapper = (props: Record) => ( - - - + ) it("returns an empty state if artist has no artworks", async () => { - renderWithHookWrappersTL() + renderWithHookWrappersTL(, getRelayEnvironment(), { includeNavigation: true }) const emptyTitle = "Get notified when new works are available" const emptyMessage = "There are currently no works for sale for this artist. Create an alert, and we’ll let you know when new works are added." @@ -70,7 +68,7 @@ describe("Artist", () => { }) it("should render all tabs", async () => { - renderWithHookWrappersTL() + renderWithHookWrappersTL(, getRelayEnvironment(), { includeNavigation: true }) mockMostRecentOperation("ArtistAboveTheFoldQuery") mockMostRecentOperation("ArtistBelowTheFoldQuery", { @@ -88,7 +86,7 @@ describe("Artist", () => { }) it("tracks a page view", async () => { - renderWithHookWrappersTL() + renderWithHookWrappersTL(, getRelayEnvironment(), { includeNavigation: true }) mockMostRecentOperation("ArtistAboveTheFoldQuery") @@ -104,7 +102,7 @@ describe("Artist", () => { }) it("displays follow button for artist with formatted follow count", () => { - renderWithHookWrappersTL() + renderWithHookWrappersTL(, getRelayEnvironment(), { includeNavigation: true }) mockMostRecentOperation("ArtistAboveTheFoldQuery", { Artist() { @@ -122,7 +120,7 @@ describe("Artist", () => { }) it("tracks follow change on follow button click", async () => { - renderWithHookWrappersTL() + renderWithHookWrappersTL(, getRelayEnvironment(), { includeNavigation: true }) mockMostRecentOperation("ArtistAboveTheFoldQuery", { Artist() { diff --git a/src/app/Scenes/Artwork/Artwork.tests.tsx b/src/app/Scenes/Artwork/Artwork.tests.tsx index 2225cebec31..7308cf7a714 100644 --- a/src/app/Scenes/Artwork/Artwork.tests.tsx +++ b/src/app/Scenes/Artwork/Artwork.tests.tsx @@ -19,7 +19,6 @@ import { import { ArtworkFixture } from "app/__fixtures__/ArtworkFixture" import { __globalStoreTestUtils__ } from "app/store/GlobalStore" -import { ModalStack } from "app/system/navigation/ModalStack" import { navigationEvents } from "app/system/navigation/navigate" import { getMockRelayEnvironment } from "app/system/relay/defaultEnvironment" import { flushPromiseQueue } from "app/utils/tests/flushPromiseQueue" @@ -57,15 +56,13 @@ describe("Artwork", () => { let environment: ReturnType const TestRenderer = ({ isVisible = true, onLoad = jest.fn() }) => ( - - - + ) beforeEach(() => { @@ -78,7 +75,7 @@ describe("Artwork", () => { }) it("renders above the fold content before the full query has been resolved", async () => { - renderWithWrappers() + renderWithWrappers(, { includeNavigation: true }) // ArtworkAboveTheFoldQuery resolveMostRecentRelayOperation(environment) @@ -92,7 +89,7 @@ describe("Artwork", () => { }) it("renders all content after the full query has been resolved", async () => { - renderWithWrappers() + renderWithWrappers(, { includeNavigation: true }) // ArtworkAboveTheFoldQuery resolveMostRecentRelayOperation(environment, { @@ -128,7 +125,7 @@ describe("Artwork", () => { describe("artist series components", () => { it("renders when there are artist series to show", async () => { - renderWithWrappers() + renderWithWrappers(, { includeNavigation: true }) // ArtworkAboveTheFoldQuery resolveMostRecentRelayOperation(environment, { @@ -167,7 +164,7 @@ describe("Artwork", () => { }) it("does not render when there are no artist series to show", async () => { - renderWithWrappers() + renderWithWrappers(, { includeNavigation: true }) // ArtworkAboveTheFoldQuery resolveMostRecentRelayOperation(environment) @@ -200,7 +197,7 @@ describe("Artwork", () => { }) it("tracks a click to an artist series item", async () => { - renderWithWrappers() + renderWithWrappers(, { includeNavigation: true }) // ArtworkAboveTheFoldQuery resolveMostRecentRelayOperation(environment, { @@ -274,7 +271,7 @@ describe("Artwork", () => { }) it("renders the ArtworkDetails component when conditionDescription is null but canRequestLotConditionsReport is true", async () => { - renderWithWrappers() + renderWithWrappers(, { includeNavigation: true }) // ArtworkAboveTheFoldQuery resolveMostRecentRelayOperation(environment) @@ -306,7 +303,7 @@ describe("Artwork", () => { it("updates the above-the-fold content on re-appear", async () => { // eslint-disable-next-line testing-library/render-result-naming-convention - const tree = renderWithWrappers() + const tree = renderWithWrappers(, { includeNavigation: true }) // ArtworkAboveTheFoldQuery resolveMostRecentRelayOperation(environment, { @@ -386,7 +383,7 @@ describe("Artwork", () => { describe("Live Auction States", () => { describe("has the correct state for a work that is in an auction that is currently live", () => { it("for which I am registered", () => { - renderWithWrappers() + renderWithWrappers(, { includeNavigation: true }) // ArtworkAboveTheFoldQuery resolveMostRecentRelayOperation(environment, { @@ -404,7 +401,7 @@ describe("Artwork", () => { }) it("for which I am not registered and registration is open", async () => { - renderWithWrappers() + renderWithWrappers(, { includeNavigation: true }) // ArtworkAboveTheFoldQuery resolveMostRecentRelayOperation(environment, { @@ -425,7 +422,7 @@ describe("Artwork", () => { }) it("for which I am not registered and registration is closed", () => { - renderWithWrappers() + renderWithWrappers(, { includeNavigation: true }) // ArtworkAboveTheFoldQuery resolveMostRecentRelayOperation(environment, { @@ -446,7 +443,7 @@ describe("Artwork", () => { describe("Partner Section", () => { it("should display contact gallery button when partner is inquireable", () => { - renderWithWrappers() + renderWithWrappers(, { includeNavigation: true }) // ArtworkAboveTheFoldQuery resolveMostRecentRelayOperation(environment, { @@ -487,7 +484,7 @@ describe("Artwork", () => { }) it("should not display contact gallery button when partner is not inquireable", () => { - renderWithWrappers() + renderWithWrappers(, { includeNavigation: true }) // ArtworkAboveTheFoldQuery resolveMostRecentRelayOperation(environment, { @@ -529,7 +526,7 @@ describe("Artwork", () => { describe("Shipping and taxes", () => { it("should be rendered when the work has `for sale` availability", async () => { - renderWithWrappers() + renderWithWrappers(, { includeNavigation: true }) // ArtworkAboveTheFoldQuery resolveMostRecentRelayOperation(environment, { @@ -555,7 +552,7 @@ describe("Artwork", () => { }) it("should NOT be rendered if the work has any other availability", () => { - renderWithWrappers() + renderWithWrappers(, { includeNavigation: true }) // ArtworkAboveTheFoldQuery resolveMostRecentRelayOperation(environment) // ArtworkMarkAsRecentlyViewedQuery @@ -572,7 +569,7 @@ describe("Artwork", () => { }) it("should NOT be rendered if the work is in auction", () => { - renderWithWrappers() + renderWithWrappers(, { includeNavigation: true }) // ArtworkAboveTheFoldQuery resolveMostRecentRelayOperation(environment, { @@ -597,7 +594,7 @@ describe("Artwork", () => { describe("Artsy Guarantee section", () => { it("should be displayed when eligible for artsy guarantee", async () => { - renderWithWrappers() + renderWithWrappers(, { includeNavigation: true }) // ArtworkAboveTheFoldQuery resolveMostRecentRelayOperation(environment, { @@ -632,7 +629,7 @@ describe("Artwork", () => { }) it("should not be displayed when ineligible for artsy guarantee", async () => { - renderWithWrappers() + renderWithWrappers(, { includeNavigation: true }) // ArtworkAboveTheFoldQuery resolveMostRecentRelayOperation(environment) @@ -656,7 +653,7 @@ describe("Artwork", () => { describe("Context Card", () => { it("should NOT be displayed if the work is in a non-auction sale", async () => { - renderWithWrappers() + renderWithWrappers(, { includeNavigation: true }) // ArtworkAboveTheFoldQuery resolveMostRecentRelayOperation(environment, { @@ -681,7 +678,7 @@ describe("Artwork", () => { }) it("should be displayed if the work is in an auction", async () => { - renderWithWrappers() + renderWithWrappers(, { includeNavigation: true }) // ArtworkAboveTheFoldQuery resolveMostRecentRelayOperation(environment, { @@ -716,7 +713,7 @@ describe("Artwork", () => { describe("About the work section", () => { it("should NOT be rendered", async () => { - renderWithWrappers() + renderWithWrappers(, { includeNavigation: true }) // ArtworkAboveTheFoldQuery resolveMostRecentRelayOperation(environment) @@ -737,7 +734,7 @@ describe("Artwork", () => { }) it("should be rendered", async () => { - renderWithWrappers() + renderWithWrappers(, { includeNavigation: true }) // ArtworkAboveTheFoldQuery resolveMostRecentRelayOperation(environment) @@ -759,7 +756,7 @@ describe("Artwork", () => { describe("Provenance/Exhibition history/Bibliography", () => { it("should NOT be rendered", async () => { - renderWithWrappers() + renderWithWrappers(, { includeNavigation: true }) // ArtworkAboveTheFoldQuery resolveMostRecentRelayOperation(environment) @@ -783,7 +780,7 @@ describe("Artwork", () => { }) it("should be rendered", async () => { - renderWithWrappers() + renderWithWrappers(, { includeNavigation: true }) // ArtworkAboveTheFoldQuery resolveMostRecentRelayOperation(environment) @@ -809,7 +806,7 @@ describe("Artwork", () => { describe("About the artist", () => { it("should NOT be rendered", async () => { - renderWithWrappers() + renderWithWrappers(, { includeNavigation: true }) // ArtworkAboveTheFoldQuery resolveMostRecentRelayOperation(environment) @@ -829,7 +826,7 @@ describe("Artwork", () => { }) it("should be rendered", async () => { - renderWithWrappers() + renderWithWrappers(, { includeNavigation: true }) // ArtworkAboveTheFoldQuery resolveMostRecentRelayOperation(environment) @@ -855,7 +852,7 @@ describe("Artwork", () => { describe("Other works", () => { it("should NOT be rendered", async () => { - renderWithWrappers() + renderWithWrappers(, { includeNavigation: true }) // ArtworkAboveTheFoldQuery resolveMostRecentRelayOperation(environment) @@ -882,7 +879,7 @@ describe("Artwork", () => { }) it("should be rendered", async () => { - renderWithWrappers() + renderWithWrappers(, { includeNavigation: true }) // ArtworkAboveTheFoldQuery resolveMostRecentRelayOperation(environment, { @@ -933,7 +930,7 @@ describe("Artwork", () => { describe("Consigments", () => { it("shows consign link if at least 1 artist is consignable", async () => { - renderWithWrappers() + renderWithWrappers(, { includeNavigation: true }) // ArtworkAboveTheFoldQuery resolveMostRecentRelayOperation(environment) @@ -958,7 +955,7 @@ describe("Artwork", () => { }) it("doesn't render section", async () => { - renderWithWrappers() + renderWithWrappers(, { includeNavigation: true }) // ArtworkAboveTheFoldQuery resolveMostRecentRelayOperation(environment, { @@ -993,7 +990,7 @@ describe("Artwork", () => { describe("Unlisted Private Artworks", () => { it("renders correct components for unlisted private artworks", async () => { - renderWithWrappers() + renderWithWrappers(, { includeNavigation: true }) // ArtworkAboveTheFoldQuery resolveMostRecentRelayOperation(environment, { @@ -1041,7 +1038,7 @@ describe("Artwork", () => { }) it("tracks partner name taps", async () => { - renderWithWrappers() + renderWithWrappers(, { includeNavigation: true }) // ArtworkAboveTheFoldQuery resolveMostRecentRelayOperation(environment, { diff --git a/src/app/Scenes/Artwork/Components/ArtworkConsignments.tests.tsx b/src/app/Scenes/Artwork/Components/ArtworkConsignments.tests.tsx index ba855bea22d..bd6b5bceb3b 100644 --- a/src/app/Scenes/Artwork/Components/ArtworkConsignments.tests.tsx +++ b/src/app/Scenes/Artwork/Components/ArtworkConsignments.tests.tsx @@ -1,7 +1,6 @@ import { fireEvent, screen } from "@testing-library/react-native" import { ArtworkConsignments_artwork_TestQuery } from "__generated__/ArtworkConsignments_artwork_TestQuery.graphql" import { ArtworkFixture } from "app/__fixtures__/ArtworkFixture" -import { ModalStack } from "app/system/navigation/ModalStack" import { switchTab } from "app/system/navigation/navigate" import { flushPromiseQueue } from "app/utils/tests/flushPromiseQueue" import { renderWithHookWrappersTL } from "app/utils/tests/renderWithWrappers" @@ -34,11 +33,7 @@ describe("ArtworkConsignments", () => { ) if (data.artwork) { - return ( - - - - ) + return } return null diff --git a/src/app/Scenes/Artwork/Components/ArtworkExtraLinks/index.tests.tsx b/src/app/Scenes/Artwork/Components/ArtworkExtraLinks/index.tests.tsx index 6f8c5821bfa..67560dca225 100644 --- a/src/app/Scenes/Artwork/Components/ArtworkExtraLinks/index.tests.tsx +++ b/src/app/Scenes/Artwork/Components/ArtworkExtraLinks/index.tests.tsx @@ -2,7 +2,6 @@ import { fireEvent, screen } from "@testing-library/react-native" import { ArtworkExtraLinks_artwork$data } from "__generated__/ArtworkExtraLinks_artwork.graphql" import { AuctionTimerState } from "app/Components/Bidding/Components/Timer" import { ArtworkFixture } from "app/__fixtures__/ArtworkFixture" -import { ModalStack } from "app/system/navigation/ModalStack" import { switchTab } from "app/system/navigation/navigate" import { CleanRelayFragment } from "app/utils/relayHelpers" import { mockTrackEvent } from "app/utils/tests/globallyMockedStuff" @@ -20,11 +19,7 @@ const getWrapper = ({ artwork: CleanRelayFragment auctionState?: AuctionTimerState }) => - renderWithWrappers( - - - - ) + renderWithWrappers() describe("ArtworkExtraLinks", () => { it("redirects to sell tab", () => { diff --git a/src/app/Scenes/Artwork/Components/CertificateAuthenticity.tsx b/src/app/Scenes/Artwork/Components/CertificateAuthenticity.tsx index bb363e622cd..ec967662766 100644 --- a/src/app/Scenes/Artwork/Components/CertificateAuthenticity.tsx +++ b/src/app/Scenes/Artwork/Components/CertificateAuthenticity.tsx @@ -1,41 +1,10 @@ -import { - Spacer, - Box, - Text, - Join, - Button, - Screen, - Touchable, - CloseIcon, - useSpace, -} from "@artsy/palette-mobile" +import { Box, Button, Join, Screen, Spacer, Text } from "@artsy/palette-mobile" import { goBack, navigate } from "app/system/navigation/navigate" -import { useAndroidGoBack } from "app/utils/hooks/useBackHandler" -import { useFeatureFlag } from "app/utils/hooks/useFeatureFlag" import { ScrollView } from "react-native" export const CertificateOfAuthenticity: React.FC = () => { - useAndroidGoBack() - const space = useSpace() - const enableNewNavigation = useFeatureFlag("AREnableNewNavigation") - return ( - {!enableNewNavigation && ( - goBack()} - hitSlop={{ top: space(2), left: space(2), bottom: space(2), right: space(2) }} - > - - - } - /> - )} - diff --git a/src/app/Scenes/ArtworkAttributionClassFAQ/ArtworkAttributionClassFAQ.tsx b/src/app/Scenes/ArtworkAttributionClassFAQ/ArtworkAttributionClassFAQ.tsx index 0c822dc7b9b..f2b62b1d182 100644 --- a/src/app/Scenes/ArtworkAttributionClassFAQ/ArtworkAttributionClassFAQ.tsx +++ b/src/app/Scenes/ArtworkAttributionClassFAQ/ArtworkAttributionClassFAQ.tsx @@ -1,21 +1,8 @@ -import { - Box, - Button, - CloseIcon, - Join, - Screen, - Separator, - Spacer, - Text, - Touchable, - useSpace, -} from "@artsy/palette-mobile" +import { Box, Button, Join, Screen, Separator, Spacer, Text } from "@artsy/palette-mobile" import { ArtworkAttributionClassFAQQuery } from "__generated__/ArtworkAttributionClassFAQQuery.graphql" import { ArtworkAttributionClassFAQ_artworkAttributionClasses$data } from "__generated__/ArtworkAttributionClassFAQ_artworkAttributionClasses.graphql" import { goBack } from "app/system/navigation/navigate" import { getRelayEnvironment } from "app/system/relay/defaultEnvironment" -import { useAndroidGoBack } from "app/utils/hooks/useBackHandler" -import { useFeatureFlag } from "app/utils/hooks/useFeatureFlag" import renderWithLoadProgress from "app/utils/renderWithLoadProgress" import React from "react" import { ScrollView } from "react-native" @@ -26,27 +13,8 @@ interface Props { } export const ArtworkAttributionClassFAQ: React.FC = ({ artworkAttributionClasses }) => { - const space = useSpace() - const enableNewNavigation = useFeatureFlag("AREnableNewNavigation") - - useAndroidGoBack() return ( - {!enableNewNavigation && ( - goBack()} - hitSlop={{ top: space(2), left: space(2), bottom: space(2), right: space(2) }} - > - - - } - /> - )} - diff --git a/src/app/Scenes/ArtworkMedium/ArtworkMedium.tsx b/src/app/Scenes/ArtworkMedium/ArtworkMedium.tsx index 2595fb4ac34..df13286477c 100644 --- a/src/app/Scenes/ArtworkMedium/ArtworkMedium.tsx +++ b/src/app/Scenes/ArtworkMedium/ArtworkMedium.tsx @@ -1,21 +1,8 @@ -import { - Box, - Button, - CloseIcon, - Join, - Screen, - Separator, - Spacer, - Text, - Touchable, - useSpace, -} from "@artsy/palette-mobile" +import { Box, Button, Join, Screen, Separator, Spacer, Text } from "@artsy/palette-mobile" import { ArtworkMediumQuery } from "__generated__/ArtworkMediumQuery.graphql" import { ArtworkMedium_artwork$data } from "__generated__/ArtworkMedium_artwork.graphql" import { goBack } from "app/system/navigation/navigate" import { getRelayEnvironment } from "app/system/relay/defaultEnvironment" -import { useAndroidGoBack } from "app/utils/hooks/useBackHandler" -import { useFeatureFlag } from "app/utils/hooks/useFeatureFlag" import renderWithLoadProgress from "app/utils/renderWithLoadProgress" import { ScrollView } from "react-native" import { createFragmentContainer, graphql, QueryRenderer } from "react-relay" @@ -25,27 +12,8 @@ interface Props { } export const ArtworkMedium: React.FC = ({ artwork }) => { - const space = useSpace() - const enableNewNavigation = useFeatureFlag("AREnableNewNavigation") - - useAndroidGoBack() - return ( - {!enableNewNavigation && ( - goBack()} - hitSlop={{ top: space(2), left: space(2), bottom: space(2), right: space(2) }} - > - - - } - /> - )} diff --git a/src/app/Scenes/AuctionResult/AuctionResult.tsx b/src/app/Scenes/AuctionResult/AuctionResult.tsx index 72b6ab681d1..2c20f7f771b 100644 --- a/src/app/Scenes/AuctionResult/AuctionResult.tsx +++ b/src/app/Scenes/AuctionResult/AuctionResult.tsx @@ -4,12 +4,11 @@ import { Flex, Join, NoArtworkIcon, + Separator, Spacer, Text, useSpace, useTheme, - Separator, - BackButton, } from "@artsy/palette-mobile" import { NavigationProp, useNavigation } from "@react-navigation/native" import { addBreadcrumb } from "@sentry/react-native" @@ -22,10 +21,9 @@ import { import { ratioColor } from "app/Components/AuctionResult/AuctionResultMidEstimate" import { InfoButton } from "app/Components/Buttons/InfoButton" import { AuthenticatedRoutesParams } from "app/Navigation/AuthenticatedRoutes/Tabs" -import { goBack, navigate } from "app/system/navigation/navigate" +import { navigate } from "app/system/navigation/navigate" import { QAInfoPanel } from "app/utils/QAInfo" import { useScreenDimensions } from "app/utils/hooks" -import { useFeatureFlag } from "app/utils/hooks/useFeatureFlag" import { PlaceholderBox } from "app/utils/placeholders" import { getImageSquareDimensions } from "app/utils/resizeImage" import { ProvideScreenTrackingWithCohesionSchema } from "app/utils/track" @@ -51,10 +49,8 @@ export const AuctionResult: React.FC = (props) => { const artist = useFragment(artistFragment, props.artist) const auctionResult = useFragment(auctionResultFragment, props.auctionResult) const navigation = useNavigation>() - const enableNewNavigation = useFeatureFlag("AREnableNewNavigation") const { theme } = useTheme() - const space = useSpace() const tracking = useTracking() @@ -235,21 +231,6 @@ export const AuctionResult: React.FC = (props) => { return ( - {!enableNewNavigation && ( - - - - - - {auctionResult.title} - - {!!auctionResult.dateText && , {auctionResult.dateText}} - - )} - }> {!!auctionResult?.images?.larger && ( diff --git a/src/app/Scenes/BottomTabs/BottomTabs.tests.tsx b/src/app/Scenes/BottomTabs/BottomTabs.tests.tsx deleted file mode 100644 index 76f7cec79b1..00000000000 --- a/src/app/Scenes/BottomTabs/BottomTabs.tests.tsx +++ /dev/null @@ -1,228 +0,0 @@ -import { BottomTabBarProps } from "@react-navigation/bottom-tabs" -import { screen, waitFor, within } from "@testing-library/react-native" -import { LegacyNativeModules } from "app/NativeModules/LegacyNativeModules" -import { BottomTabsButtonProps } from "app/Scenes/BottomTabs/BottomTabsButton" -import { __globalStoreTestUtils__ } from "app/store/GlobalStore" -import { ModalStack } from "app/system/navigation/ModalStack" -import { bottomTabsRelayEnvironment } from "app/system/relay/defaultEnvironment" -import { flushPromiseQueue } from "app/utils/tests/flushPromiseQueue" -import { renderWithWrappers as _renderWithWrappers } from "app/utils/tests/renderWithWrappers" -import { resolveMostRecentRelayOperation } from "app/utils/tests/resolveMostRecentRelayOperation" -import { ReactElement } from "react" -import { RelayEnvironmentProvider } from "react-relay" -import { MockEnvironment } from "relay-test-utils" -import { MockResolvers } from "relay-test-utils/lib/RelayMockPayloadGenerator" -import { BottomTabs, FETCH_NOTIFICATIONS_INFO_INTERVAL } from "./BottomTabs" - -describe(BottomTabs, () => { - const mockEnvironment = bottomTabsRelayEnvironment as unknown as MockEnvironment - - const renderWithWrappers = (component: ReactElement) => { - return _renderWithWrappers(component, { skipRelay: true }) - } - - const TestWrapper = (props: Partial) => { - return ( - - - {/* @ts-ignore */} - - - - ) - } - - afterEach(() => { - jest.clearAllMocks() - }) - - it("displays the current unread notifications count", async () => { - __globalStoreTestUtils__?.injectState({ - bottomTabs: { sessionState: { unreadCounts: { conversations: 4 } } }, - }) - - renderWithWrappers() - - const counter = await findBadgeCounterForTab("inbox") - expect(counter).toHaveTextContent("4") - }) - - describe("a blue dot on home icon", () => { - it("should be displayed if there are unseen notifications", async () => { - renderWithWrappers() - - expect(screen.queryByLabelText("home visual clue")).toBeFalsy() - - resolveNotificationsInfoQuery(mockEnvironment, { - Me: () => ({ - unreadConversationCount: 5, - unseenNotificationsCount: 1, - }), - }) - - await flushPromiseQueue() - - expect(screen.getByLabelText("home visual clue")).toBeTruthy() - }) - - it("should NOT be displayed if there are NO unseen notifications", async () => { - renderWithWrappers() - - expect(screen.queryByLabelText("home visual clue")).toBeFalsy() - - resolveNotificationsInfoQuery(mockEnvironment, { - Me: () => ({ - unreadConversationCount: 5, - unseenNotificationsCount: 0, - }), - }) - - await flushPromiseQueue() - - expect(screen.queryByLabelText("home visual clue")).toBeFalsy() - }) - }) - - it("sets the application icon badge count", async () => { - renderWithWrappers() - - resolveNotificationsInfoQuery(mockEnvironment, { - Me: () => ({ - unreadConversationCount: 9, - unseenNotificationsCount: 1, - unreadNotificationsCount: 1, - }), - }) - - await flushPromiseQueue() - - const fn = LegacyNativeModules.ARTemporaryAPIModule.setApplicationIconBadgeNumber - expect(fn).toHaveBeenCalledWith(10) - }) - - it("should not be rendered if the `hidesBottomTabs` option is specified", async () => { - const state: BottomTabBarProps["state"] = { - ...navigationState, - routes: [ - { - key: "route-key", - name: "route", - params: { - moduleName: "Artwork", - }, - }, - ], - } - - renderWithWrappers() - - expect(screen.queryByLabelText("home bottom tab")).toBeFalsy() - expect(screen.queryByLabelText("search bottom tab")).toBeFalsy() - expect(screen.queryByLabelText("inbox bottom tab")).toBeFalsy() - expect(screen.queryByLabelText("sell bottom tab")).toBeFalsy() - expect(screen.queryByLabelText("profile bottom tab")).toBeFalsy() - }) - - it("fetches the notifications info on mount", async () => { - renderWithWrappers() - - expect(mockEnvironment.mock.getAllOperations()).toHaveLength(1) - - resolveNotificationsInfoQuery(mockEnvironment, { - Me: () => ({ - unreadConversationCount: 5, - unseenNotificationsCount: 1, - }), - }) - - const counter = await findBadgeCounterForTab("inbox") - expect(counter).toHaveTextContent("5") - - const homeButton = screen.getByLabelText("home bottom tab") - expect(within(homeButton).getByLabelText("home visual clue")).toBeTruthy() - }) - - /** - * This test case should be placed last, otherwise after `jest.useRealTimers` - * we will get `setImmediate is not a function` error for the next test cases - * It is related to this problem: https://github.com/artsy/eigen/blob/main/HACKS.md#jestfake-timers - */ - it("fetches the notifications info once in a while", async () => { - jest.useFakeTimers({ - legacyFakeTimers: true, - }) - - renderWithWrappers() - - // Initial query on mount - resolveNotificationsInfoQuery(mockEnvironment, { - Me: () => ({ - unreadConversationCount: 5, - }), - }) - expect(mockEnvironment.mock.getAllOperations()).toHaveLength(0) - - // Check badge counters for initial query - const prevInboxCounter = await findBadgeCounterForTab("inbox") - expect(prevInboxCounter).toHaveTextContent("5") - - // fast-forward until 1st call should be executed - jest.advanceTimersByTime(FETCH_NOTIFICATIONS_INFO_INTERVAL) - - expect(mockEnvironment.mock.getAllOperations()).toHaveLength(1) - resolveNotificationsInfoQuery(mockEnvironment, { - Me: () => ({ - unreadConversationCount: 3, - }), - }) - - // Check badge counters - const currentInboxCounter = await findBadgeCounterForTab("inbox") - expect(currentInboxCounter).toHaveTextContent("3") - }) -}) - -const navigationState: BottomTabBarProps["state"] = { - history: [ - { - key: "route-key", - type: "route", - }, - ], - index: 0, - key: "tab-key", - routeNames: ["route-name"], - routes: [ - { - key: "route-key", - name: "route", - params: { - moduleName: "moduleName", - }, - }, - ], - stale: false, - type: "tab", -} - -const resolveNotificationsInfoQuery = ( - mockEnvironment: MockEnvironment, - resolvers: MockResolvers -) => { - expect(mockEnvironment.mock.getMostRecentOperation().request.node.operation.name).toBe( - "BottomTabsModelFetchNotificationsInfoQuery" - ) - - resolveMostRecentRelayOperation(mockEnvironment, resolvers) -} - -const findButtonByTabName = (tabName: BottomTabsButtonProps["tab"]) => { - return screen.getByLabelText(`${tabName} bottom tab`) -} - -const findBadgeCounterForTab = async (tabName: BottomTabsButtonProps["tab"]) => { - const button = findButtonByTabName(tabName) - const result = await waitFor(() => within(button).getByLabelText("badge count")) - - return result -} diff --git a/src/app/Scenes/BottomTabs/BottomTabs.tsx b/src/app/Scenes/BottomTabs/BottomTabs.tsx deleted file mode 100644 index 261f3e19e01..00000000000 --- a/src/app/Scenes/BottomTabs/BottomTabs.tsx +++ /dev/null @@ -1,61 +0,0 @@ -import { Flex, useTheme, Separator } from "@artsy/palette-mobile" -import { BottomTabBarProps } from "@react-navigation/bottom-tabs" -import { findFocusedRoute } from "@react-navigation/native" -import { AppModule, modules } from "app/AppRegistry" -import { GlobalStore } from "app/store/GlobalStore" -import { useIsStaging } from "app/utils/hooks/useIsStaging" -import { useEffect } from "react" -import { useSafeAreaInsets } from "react-native-safe-area-context" -import useInterval from "react-use/lib/useInterval" -import { BOTTOM_TABS_TEXT_HEIGHT, BottomTabsButton } from "./BottomTabsButton" -import { ICON_HEIGHT } from "./BottomTabsIcon" - -export const FETCH_NOTIFICATIONS_INFO_INTERVAL = 60 * 1000 // every 60 seconds -export const BOTTOM_TABS_HEIGHT = ICON_HEIGHT + BOTTOM_TABS_TEXT_HEIGHT - -export const BottomTabs: React.FC = (props) => { - const { color } = useTheme() - const focusedRoute = findFocusedRoute(props.state) - const params = focusedRoute?.params as any - const module = modules[params?.moduleName as AppModule] - const unreadConversationsCount = GlobalStore.useAppState( - (state) => state.bottomTabs.sessionState.unreadCounts.conversations - ) - const hasUnseenNotifications = GlobalStore.useAppState( - (state) => state.bottomTabs.hasUnseenNotifications - ) - - useEffect(() => { - GlobalStore.actions.bottomTabs.fetchNotificationsInfo() - }, []) - - useInterval(() => { - GlobalStore.actions.bottomTabs.fetchNotificationsInfo() - // run this every 60 seconds - }, FETCH_NOTIFICATIONS_INFO_INTERVAL) - - const isStaging = useIsStaging() - - const { bottom } = useSafeAreaInsets() - - if (module?.options?.hidesBottomTabs) { - return null - } - - return ( - - - - - - - - - - - ) -} diff --git a/src/app/Scenes/BottomTabs/BottomTabsButton.tests.tsx b/src/app/Scenes/BottomTabs/BottomTabsButton.tests.tsx deleted file mode 100644 index 0dcca3ae858..00000000000 --- a/src/app/Scenes/BottomTabs/BottomTabsButton.tests.tsx +++ /dev/null @@ -1,80 +0,0 @@ -import { Touchable } from "@artsy/palette-mobile" -import { __globalStoreTestUtils__, GlobalStoreProvider } from "app/store/GlobalStore" -import { ModalStack } from "app/system/navigation/ModalStack" -import { switchTab } from "app/system/navigation/navigate" -import { extractText } from "app/utils/tests/extractText" -import { flushPromiseQueue } from "app/utils/tests/flushPromiseQueue" -import { mockTrackEvent } from "app/utils/tests/globallyMockedStuff" -import { renderWithWrappersLEGACY } from "app/utils/tests/renderWithWrappers" -import { BottomTabsButton } from "./BottomTabsButton" - -const TestWrapper: React.FC> = (props) => { - return ( - - - - - - ) -} - -describe(BottomTabsButton, () => { - describe("when AREnableNewNavigation is false", () => { - beforeEach(() => { - __globalStoreTestUtils__?.injectFeatureFlags({ - AREnableNewNavigation: false, - }) - }) - it(`updates the selected tab state on press`, async () => { - const tree = renderWithWrappersLEGACY() - expect(__globalStoreTestUtils__?.getCurrentState().bottomTabs.sessionState.selectedTab).toBe( - "home" - ) - tree.root.findByType(Touchable).props.onPress() - await flushPromiseQueue() - expect(switchTab).toHaveBeenCalledWith("search") - }) - - it(`dispatches an analytics action on press`, async () => { - const tree = renderWithWrappersLEGACY() - expect(mockTrackEvent).not.toHaveBeenCalled() - tree.root.findByType(Touchable).props.onPress() - await flushPromiseQueue() - expect(switchTab).toHaveBeenCalledWith("sell") - expect(mockTrackEvent).toHaveBeenCalledWith({ - action: "tappedTabBar", - badge: false, - context_module: "tabBar", - context_screen_owner_type: "home", - tab: "sell", - }) - }) - - describe(`badge`, () => { - it(`doesn't show anything when the number is 0`, async () => { - const tree = renderWithWrappersLEGACY() - expect(extractText(tree.root)).toBe("Sell") - tree.update() - expect(extractText(tree.root)).toBe("Sell") - }) - it(`shows the number when the number is bigger than 0`, async () => { - const tree = renderWithWrappersLEGACY() - expect(extractText(tree.root)).toBe("Sell1") - tree.update() - expect(extractText(tree.root)).toBe("Sell5") - tree.update() - expect(extractText(tree.root)).toBe("Sell52") - }) - it(`tops out at 99`, async () => { - const tree = renderWithWrappersLEGACY() - expect(extractText(tree.root)).toBe("Sell1") - tree.update() - expect(extractText(tree.root)).toBe("Sell99") - tree.update() - expect(extractText(tree.root)).toBe("Sell99+") - tree.update() - expect(extractText(tree.root)).toBe("Sell99+") - }) - }) - }) -}) diff --git a/src/app/Scenes/BottomTabs/BottomTabsButton.tsx b/src/app/Scenes/BottomTabs/BottomTabsButton.tsx deleted file mode 100644 index d07d071a077..00000000000 --- a/src/app/Scenes/BottomTabs/BottomTabsButton.tsx +++ /dev/null @@ -1,238 +0,0 @@ -import { tappedTabBar } from "@artsy/cohesion" -import { Flex, PopIn, Text, Touchable, VisualClueDot, useColor } from "@artsy/palette-mobile" -import { ProgressiveOnboardingFindSavedArtwork } from "app/Components/ProgressiveOnboarding/ProgressiveOnboardingFindSavedArtwork" -import { LegacyNativeModules } from "app/NativeModules/LegacyNativeModules" -import { unsafe__getSelectedTab } from "app/store/GlobalStore" -import { VisualClueName } from "app/store/config/visualClues" -import { switchTab } from "app/system/navigation/navigate" -import { useFeatureFlag } from "app/utils/hooks/useFeatureFlag" -import { useIsStaging } from "app/utils/hooks/useIsStaging" -import { useSelectedTab } from "app/utils/hooks/useSelectedTab" -import { useVisualClue } from "app/utils/hooks/useVisualClue" -import { useTabBarBadge } from "app/utils/useTabBarBadge" -import { useMemo } from "react" -import { GestureResponderEvent, LayoutAnimation, View } from "react-native" -import { useTracking } from "react-tracking" -import styled from "styled-components/native" -import { BottomTabOption, BottomTabType } from "./BottomTabType" -import { BottomTabsIcon, ICON_HEIGHT, ICON_WIDTH } from "./BottomTabsIcon" -import { bottomTabsConfig } from "./bottomTabsConfig" - -export interface BottomTabsButtonProps { - tab: BottomTabType - badgeCount?: number - visualClue?: VisualClueName - forceDisplayVisualClue?: boolean - onPress?: (e: GestureResponderEvent) => void -} - -export const BOTTOM_TABS_TEXT_HEIGHT = 15 - -// TODO: Improve this component once we remove enableNewNavigation feature flag -// There are too many rerenders happening in this component -export const BottomTabsButton: React.FC = ({ - tab, - badgeCount: badgeCountProp = 0, - visualClue, - forceDisplayVisualClue: forceDisplayVisualClueProp, - ...buttonProps -}) => { - const enableNewNavigation = useFeatureFlag("AREnableNewNavigation") - - const selectedTab = useSelectedTab() - const color = useColor() - - const isActive = selectedTab === tab - - const { unreadConversationsCount, hasUnseenNotifications } = useTabBarBadge() - - const forceDisplayVisualClue = useMemo(() => { - if (!enableNewNavigation) { - return forceDisplayVisualClueProp - } - - if (tab === "home") { - return hasUnseenNotifications - } - - return false - }, [hasUnseenNotifications, forceDisplayVisualClueProp]) - - const badgeCount = useMemo(() => { - if (!enableNewNavigation) { - return badgeCountProp - } - - if (tab === "inbox") { - return unreadConversationsCount ?? 0 - } - - return 0 - }, [unreadConversationsCount, badgeCountProp]) - - const { showVisualClue } = useVisualClue() - - const tracking = useTracking() - const isStaging = useIsStaging() - - const onPress = (e: GestureResponderEvent) => { - if (enableNewNavigation) { - buttonProps.onPress?.(e) - tracking.trackEvent( - tappedTabBar({ - tab: bottomTabsConfig[tab].analyticsDescription, - badge: badgeCount > 0, - contextScreenOwnerType: BottomTabOption[selectedTab], - }) - ) - - return - } - - LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut) - if (tab === unsafe__getSelectedTab()) { - LegacyNativeModules.ARScreenPresenterModule.popToRootOrScrollToTop(tab) - } else { - switchTab(tab) - } - tracking.trackEvent( - tappedTabBar({ - tab: bottomTabsConfig[tab].analyticsDescription, - badge: badgeCount > 0, - contextScreenOwnerType: BottomTabOption[selectedTab], - }) - ) - } - - return ( - - - - - - - - - - - - - - - - - {bottomTabsConfig[tab].name} - - - - - {!!badgeCount && ( - - - - - - - - - - )} - {(!!showVisualClue(visualClue) || !!forceDisplayVisualClue) && ( - - - - - - - - - - )} - - - ) -} - -const Badge: React.FC<{ count: number }> = ({ count }) => { - const color = useColor() - const badgeSize = 18 - const borderWidth = 2 - return ( - // we need to hack together our own 2px white border here, otherwise the red background - // bleeds into the antialiasing around the outer edge of the border :/ - - - - {count > 99 ? "99+" : count} - - - - ) -} - -const IconWrapper = styled(View)` - position: absolute; - left: 0px; - right: 0px; - top: 0px; - bottom: 0px; - align-items: center; - justify-content: center; -` diff --git a/src/app/Scenes/BottomTabs/BottomTabsNavigator.tests.tsx b/src/app/Scenes/BottomTabs/BottomTabsNavigator.tests.tsx deleted file mode 100644 index a5bbaa089c2..00000000000 --- a/src/app/Scenes/BottomTabs/BottomTabsNavigator.tests.tsx +++ /dev/null @@ -1,30 +0,0 @@ -import { screen } from "@testing-library/react-native" -import { __globalStoreTestUtils__ } from "app/store/GlobalStore" -import { ModalStack } from "app/system/navigation/ModalStack" -import { renderWithWrappers } from "app/utils/tests/renderWithWrappers" -import { BottomTabsNavigator } from "./BottomTabsNavigator" - -describe(BottomTabsNavigator, () => { - beforeEach(() => { - __globalStoreTestUtils__?.injectFeatureFlags({ AREnableNewNavigation: false }) - }) - - it("shows the current tab content", async () => { - renderWithWrappers( - - - - ) - - expect(screen.queryByLabelText("home bottom tab")).toBeOnTheScreen() - expect(screen.queryByLabelText("search bottom tab")).toBeOnTheScreen() - expect(screen.queryByLabelText("inbox bottom tab")).toBeOnTheScreen() - expect(screen.queryByLabelText("sell bottom tab")).toBeOnTheScreen() - expect(screen.queryByLabelText("profile bottom tab")).toBeOnTheScreen() - - expect(screen.getByAccessibilityState({ selected: true })).toHaveProp( - "accessibilityLabel", - "home bottom tab" - ) - }) -}) diff --git a/src/app/Scenes/BottomTabs/BottomTabsNavigator.tsx b/src/app/Scenes/BottomTabs/BottomTabsNavigator.tsx deleted file mode 100644 index c617bc85a34..00000000000 --- a/src/app/Scenes/BottomTabs/BottomTabsNavigator.tsx +++ /dev/null @@ -1,54 +0,0 @@ -import { createBottomTabNavigator } from "@react-navigation/bottom-tabs" -import { AppModule } from "app/AppRegistry" -import { NavStack } from "app/system/navigation/NavStack" -import { useAndroidGoBack } from "app/utils/hooks/useBackHandler" -import { BottomTabType } from "./BottomTabType" -import { BottomTabs } from "./BottomTabs" - -const Tab = createBottomTabNavigator() - -const TabContent = ({ - route, -}: { - route: { params: { tabName: BottomTabType; rootModuleName: AppModule } } -}) => { - useAndroidGoBack() - // TODO: simplify this, we probably can get rid of NavStack - return -} - -export const BottomTabsNavigator = () => { - return ( - } - backBehavior="firstRoute" - screenOptions={{ headerShown: false }} - > - - - - - - - ) -} diff --git a/src/app/Scenes/BottomTabs/useBottomTabBarHeight.ts b/src/app/Scenes/BottomTabs/useBottomTabBarHeight.ts deleted file mode 100644 index 583c3f9a93b..00000000000 --- a/src/app/Scenes/BottomTabs/useBottomTabBarHeight.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { BOTTOM_TABS_HEIGHT } from "app/Scenes/BottomTabs/BottomTabs" -import { useScreenDimensions } from "app/utils/hooks" - -const BOTTOM_TAB_SEPARATOR_HEIGHT = 1 - -export const useBottomTabBarHeight = () => { - const { safeAreaInsets } = useScreenDimensions() - - return BOTTOM_TABS_HEIGHT + safeAreaInsets.bottom + BOTTOM_TAB_SEPARATOR_HEIGHT -} diff --git a/src/app/Scenes/Collection/Components/FullFeaturedArtistList.tsx b/src/app/Scenes/Collection/Components/FullFeaturedArtistList.tsx index e574999d93d..7439b9b102a 100644 --- a/src/app/Scenes/Collection/Components/FullFeaturedArtistList.tsx +++ b/src/app/Scenes/Collection/Components/FullFeaturedArtistList.tsx @@ -2,11 +2,9 @@ import { Box } from "@artsy/palette-mobile" import { FullFeaturedArtistListQuery } from "__generated__/FullFeaturedArtistListQuery.graphql" import { FullFeaturedArtistList_collection$data } from "__generated__/FullFeaturedArtistList_collection.graphql" import { ArtistListItemContainer as ArtistListItem } from "app/Components/ArtistListItem" -import { PageWithSimpleHeader } from "app/Components/PageWithSimpleHeader" -import { unsafe_getFeatureFlag } from "app/store/GlobalStore" import { getRelayEnvironment } from "app/system/relay/defaultEnvironment" import renderWithLoadProgress from "app/utils/renderWithLoadProgress" -import React, { Fragment } from "react" +import React from "react" import { FlatList, ViewProps } from "react-native" import { createFragmentContainer, graphql, QueryRenderer } from "react-relay" @@ -38,33 +36,23 @@ export class FullFeaturedArtistList extends React.Component { render() { const allArtists = this.getFeaturedArtists() - const enableNewNavigation = unsafe_getFeatureFlag("AREnableNewNavigation") - - const Wrapper = enableNewNavigation - ? Fragment - : ({ children }: { children: React.ReactNode }) => ( - {children} - ) - return ( - - String(index)} - renderItem={({ item }) => { - return ( - // @ts-expect-error STRICTNESS_MIGRATION --- 🚨 Unsafe legacy code 🚨 Please delete this and fix any type errors if you have time 🙏 - - - - ) - }} - /> - + String(index)} + renderItem={({ item }) => { + return ( + // @ts-expect-error STRICTNESS_MIGRATION --- 🚨 Unsafe legacy code 🚨 Please delete this and fix any type errors if you have time 🙏 + + + + ) + }} + /> ) } } diff --git a/src/app/Scenes/CollectionsByCategory/__tests__/Body.tests.tsx b/src/app/Scenes/CollectionsByCategory/__tests__/Body.tests.tsx index d56a7030bcd..7d32797245d 100644 --- a/src/app/Scenes/CollectionsByCategory/__tests__/Body.tests.tsx +++ b/src/app/Scenes/CollectionsByCategory/__tests__/Body.tests.tsx @@ -5,6 +5,7 @@ import { setupTestWrapper } from "app/utils/tests/setupTestWrapper" import { graphql } from "react-relay" jest.mock("@react-navigation/native", () => ({ + ...jest.requireActual("@react-navigation/native"), useRoute: () => ({ params: { category: "mock-category" }, }), diff --git a/src/app/Scenes/CollectionsByCategory/__tests__/Footer.tests.tsx b/src/app/Scenes/CollectionsByCategory/__tests__/Footer.tests.tsx index ed841e80a6f..874336fe1b4 100644 --- a/src/app/Scenes/CollectionsByCategory/__tests__/Footer.tests.tsx +++ b/src/app/Scenes/CollectionsByCategory/__tests__/Footer.tests.tsx @@ -6,6 +6,7 @@ import { setupTestWrapper } from "app/utils/tests/setupTestWrapper" import { graphql } from "react-relay" jest.mock("@react-navigation/native", () => ({ + ...jest.requireActual("@react-navigation/native"), useRoute: () => ({ params: { category: "mock-category", diff --git a/src/app/Scenes/CompleteMyProfile/__tests__/Header.tests.tsx b/src/app/Scenes/CompleteMyProfile/__tests__/Header.tests.tsx index 7f49f51563a..9135d979327 100644 --- a/src/app/Scenes/CompleteMyProfile/__tests__/Header.tests.tsx +++ b/src/app/Scenes/CompleteMyProfile/__tests__/Header.tests.tsx @@ -4,6 +4,7 @@ import * as useCompleteProfile from "app/Scenes/CompleteMyProfile/hooks/useCompl import { renderWithWrappers } from "app/utils/tests/renderWithWrappers" jest.mock("@react-navigation/native", () => ({ + ...jest.requireActual("@react-navigation/native"), useNavigation: jest.fn(), useRoute: () => ({ name: "LocationStep" }), })) diff --git a/src/app/Scenes/HomeView/Components/__tests__/PaymentFailureBanner.tests.tsx b/src/app/Scenes/HomeView/Components/__tests__/PaymentFailureBanner.tests.tsx index d4cddbd58d3..842bc18e329 100644 --- a/src/app/Scenes/HomeView/Components/__tests__/PaymentFailureBanner.tests.tsx +++ b/src/app/Scenes/HomeView/Components/__tests__/PaymentFailureBanner.tests.tsx @@ -12,6 +12,7 @@ jest.mock("app/Scenes/HomeView/hooks/useHomeViewTracking", () => ({ })) jest.mock("@react-navigation/native", () => ({ + ...jest.requireActual("@react-navigation/native"), useIsFocused: () => mockUseIsFocusedMock(), })) diff --git a/src/app/Scenes/HomeView/HomeView.tsx b/src/app/Scenes/HomeView/HomeView.tsx index c3e8ef68439..94b61cc4d30 100644 --- a/src/app/Scenes/HomeView/HomeView.tsx +++ b/src/app/Scenes/HomeView/HomeView.tsx @@ -42,7 +42,7 @@ export const homeViewScreenQueryVariables = () => ({ }) export const HomeView: React.FC = () => { - const flashlistRef = useBottomTabsScrollToTop("home") + const flashlistRef = useBottomTabsScrollToTop() const [isRefreshing, setIsRefreshing] = useState(false) const { fetchKey } = useRetryErrorBoundaryContext() diff --git a/src/app/Scenes/Inbox/Screens/Conversation.tsx b/src/app/Scenes/Inbox/Screens/Conversation.tsx index 711e39db0fb..ff1df4d9ab3 100644 --- a/src/app/Scenes/Inbox/Screens/Conversation.tsx +++ b/src/app/Scenes/Inbox/Screens/Conversation.tsx @@ -1,3 +1,4 @@ +import { OwnerType } from "@artsy/cohesion" import { BackButton, InfoCircleIcon, Touchable } from "@artsy/palette-mobile" import NetInfo from "@react-native-community/netinfo" import { ConversationQuery } from "__generated__/ConversationQuery.graphql" @@ -15,7 +16,7 @@ import { goBack, navigate, navigationEvents } from "app/system/navigation/naviga import { getRelayEnvironment } from "app/system/relay/defaultEnvironment" import NavigatorIOS from "app/utils/__legacy_do_not_use__navigator-ios-shim" import renderWithLoadProgress from "app/utils/renderWithLoadProgress" -import { track as _track, Schema, Track } from "app/utils/track" +import { track as _track, ProvideScreenTracking, Schema, Track } from "app/utils/track" import React from "react" import { createRefetchContainer, graphql, QueryRenderer, RelayRefetchProp } from "react-relay" import styled from "styled-components/native" @@ -256,20 +257,28 @@ export const ConversationQueryRenderer: React.FC<{ }> = (props) => { const { conversationID, navigator } = props return ( - - environment={getRelayEnvironment()} - query={graphql` - query ConversationQuery($conversationID: String!) { - me { - ...Conversation_me - } - } - `} - variables={{ - conversationID, + + > + + environment={getRelayEnvironment()} + query={graphql` + query ConversationQuery($conversationID: String!) { + me { + ...Conversation_me + } + } + `} + variables={{ + conversationID, + }} + cacheConfig={{ force: true }} + render={renderWithLoadProgress(ConversationFragmentContainer, { navigator })} + /> + ) } diff --git a/src/app/Scenes/Inbox/Screens/ConversationDetails.tsx b/src/app/Scenes/Inbox/Screens/ConversationDetails.tsx index 433d8fd72f5..71c8e12faf4 100644 --- a/src/app/Scenes/Inbox/Screens/ConversationDetails.tsx +++ b/src/app/Scenes/Inbox/Screens/ConversationDetails.tsx @@ -1,7 +1,6 @@ import { Flex } from "@artsy/palette-mobile" import { ConversationDetailsQuery } from "__generated__/ConversationDetailsQuery.graphql" import { ConversationDetails_me$data } from "__generated__/ConversationDetails_me.graphql" -import { PageWithSimpleHeader } from "app/Components/PageWithSimpleHeader" import { ItemInfoFragmentContainer } from "app/Scenes/Inbox/Components/Conversations/ItemInfo" import { OrderInformationFragmentContainer } from "app/Scenes/Inbox/Components/Conversations/OrderInformation" import { PaymentMethodFragmentContainer } from "app/Scenes/Inbox/Components/Conversations/PaymentMethod" @@ -11,9 +10,7 @@ import { ShippingFragmentContainer } from "app/Scenes/Inbox/Components/Conversat import { Support } from "app/Scenes/Inbox/Components/Conversations/Support" import { getRelayEnvironment } from "app/system/relay/defaultEnvironment" import { extractNodes } from "app/utils/extractNodes" -import { useFeatureFlag } from "app/utils/hooks/useFeatureFlag" import renderWithLoadProgress from "app/utils/renderWithLoadProgress" -import { Fragment } from "react" import { ScrollView } from "react-native" import { createFragmentContainer, graphql, QueryRenderer, RelayProp } from "react-relay" @@ -89,30 +86,20 @@ export const ConversationDetailsFragmentContainer = createFragmentContainer(Conv export const ConversationDetailsQueryRenderer: React.FC<{ conversationID: string }> = ({ conversationID }) => { - const enableNewNavigation = useFeatureFlag("AREnableNewNavigation") - - const Wrapper = enableNewNavigation - ? Fragment - : ({ children }: { children: React.ReactNode }) => ( - {children} - ) - return ( - - - environment={getRelayEnvironment()} - query={graphql` - query ConversationDetailsQuery($conversationID: String!) { - me { - ...ConversationDetails_me - } + + environment={getRelayEnvironment()} + query={graphql` + query ConversationDetailsQuery($conversationID: String!) { + me { + ...ConversationDetails_me } - `} - variables={{ - conversationID, - }} - render={renderWithLoadProgress(ConversationDetailsFragmentContainer)} - /> - + } + `} + variables={{ + conversationID, + }} + render={renderWithLoadProgress(ConversationDetailsFragmentContainer)} + /> ) } diff --git a/src/app/Scenes/MyAccount/MyAccount.tests.tsx b/src/app/Scenes/MyAccount/MyAccount.tests.tsx index 9982d42f160..69484d71040 100644 --- a/src/app/Scenes/MyAccount/MyAccount.tests.tsx +++ b/src/app/Scenes/MyAccount/MyAccount.tests.tsx @@ -1,7 +1,6 @@ import { Text } from "@artsy/palette-mobile" import { MyAccountTestsQuery } from "__generated__/MyAccountTestsQuery.graphql" import { MenuItem } from "app/Components/MenuItem" -import { __globalStoreTestUtils__ } from "app/store/GlobalStore" import { extractText } from "app/utils/tests/extractText" import { renderWithWrappersLEGACY } from "app/utils/tests/renderWithWrappers" import { Platform } from "react-native" @@ -59,9 +58,6 @@ describe(MyAccountQueryRenderer, () => { ) beforeEach(() => { mockEnvironment = createMockEnvironment() - __globalStoreTestUtils__?.injectFeatureFlags({ - AREnableNewNavigation: true, - }) }) it("truncated long emails", () => { diff --git a/src/app/Scenes/MyAccount/MyAccount.tsx b/src/app/Scenes/MyAccount/MyAccount.tsx index 1b495a98d9c..50acd401024 100644 --- a/src/app/Scenes/MyAccount/MyAccount.tsx +++ b/src/app/Scenes/MyAccount/MyAccount.tsx @@ -2,25 +2,21 @@ import { Box, Button, Flex, Spacer, Text } from "@artsy/palette-mobile" import { MyAccountQuery } from "__generated__/MyAccountQuery.graphql" import { MyAccount_me$data } from "__generated__/MyAccount_me.graphql" import { MenuItem } from "app/Components/MenuItem" -import { PageWithSimpleHeader } from "app/Components/PageWithSimpleHeader" import { SectionTitle } from "app/Components/SectionTitle" import { navigate } from "app/system/navigation/navigate" import { getRelayEnvironment } from "app/system/relay/defaultEnvironment" import { useAppleLink } from "app/utils/LinkedAccounts/apple" import { useFacebookLink } from "app/utils/LinkedAccounts/facebook" import { useGoogleLink } from "app/utils/LinkedAccounts/google" -import { useFeatureFlag } from "app/utils/hooks/useFeatureFlag" import { PlaceholderText } from "app/utils/placeholders" import { renderWithPlaceholder } from "app/utils/renderWithPlaceholder" import { times } from "lodash" -import { Fragment } from "react" import { ActivityIndicator, Image, Platform, ScrollView } from "react-native" import { createFragmentContainer, graphql, QueryRenderer, RelayProp } from "react-relay" import { PRICE_BUCKETS } from "./MyAccountEditPriceRange" const MyAccount: React.FC<{ me: MyAccount_me$data; relay: RelayProp }> = ({ me, relay }) => { const hasOnlyOneAuth = me.authentications.length + (me.hasPassword ? 1 : 0) < 2 - const enableNewNavigation = useFeatureFlag("AREnableNewNavigation") const onlyExistingAuthFor = (provider: "FACEBOOK" | "GOOGLE" | "APPLE") => { return ( @@ -72,136 +68,128 @@ const MyAccount: React.FC<{ me: MyAccount_me$data; relay: RelayProp }> = ({ me, ? PRICE_BUCKETS.find((i) => me.priceRange === i.value)?.label ?? "Select a price range" : "Select a price range" - const Wrapper = enableNewNavigation - ? Fragment - : ({ children }: { children: React.ReactNode }) => ( - {children} - ) - return ( - - - { - navigate("my-account/edit-email") - }} - /> + + { + navigate("my-account/edit-email") + }} + /> + navigate("my-account/edit-phone")} + /> + navigate("my-account/edit-price-range")} + /> + {!!me.hasPassword && ( navigate("my-account/edit-phone")} + title="Password" + value="Change password" + onPress={() => navigate("my-account/edit-password")} /> - navigate("my-account/edit-price-range")} - /> - {!!me.hasPassword && ( + )} + {!!me.paddleNumber && } + {!!showLinkedAccounts && ( + + + + + navigate("my-account/edit-password")} + title="Facebook" + disabled={loading || onlyExistingAuthFor("FACEBOOK")} + allowDisabledVisualClue + rightView={ + fbLoading ? ( + + ) : ( + + + + {facebookLinked ? "Unlink" : "Link"} + + + ) + } + onPress={ + fbLoading || onlyExistingAuthFor("FACEBOOK") + ? () => null + : () => linkOrUnlink("facebook") + } /> - )} - {!!me.paddleNumber && } - {!!showLinkedAccounts && ( - - - - - - - ) : ( - - - - {facebookLinked ? "Unlink" : "Link"} - - - ) - } - onPress={ - fbLoading || onlyExistingAuthFor("FACEBOOK") - ? () => null - : () => linkOrUnlink("facebook") - } - /> + + ) : ( + + + + {googleLinked ? "Unlink" : "Link"} + + + ) + } + onPress={ + googleLoading || onlyExistingAuthFor("GOOGLE") + ? () => null + : () => linkOrUnlink("google") + } + /> + {!!showLinkApple && ( ) : ( - {googleLinked ? "Unlink" : "Link"} + {appleLinked ? "Unlink" : "Link"} ) } onPress={ - googleLoading || onlyExistingAuthFor("GOOGLE") + appleLoading || onlyExistingAuthFor("APPLE") ? () => null - : () => linkOrUnlink("google") + : () => linkOrUnlink("apple") } /> - {!!showLinkApple && ( - - ) : ( - - - - {appleLinked ? "Unlink" : "Link"} - - - ) - } - onPress={ - appleLoading || onlyExistingAuthFor("APPLE") - ? () => null - : () => linkOrUnlink("apple") - } - /> - )} - - )} - - - - + )} + + )} + + + ) } diff --git a/src/app/Scenes/MyAccount/MyAccountEditEmail.tsx b/src/app/Scenes/MyAccount/MyAccountEditEmail.tsx index d60fc4627fa..c1682b4d929 100644 --- a/src/app/Scenes/MyAccount/MyAccountEditEmail.tsx +++ b/src/app/Scenes/MyAccount/MyAccountEditEmail.tsx @@ -2,14 +2,12 @@ import { Flex, Input, Text, Touchable } from "@artsy/palette-mobile" import { useNavigation } from "@react-navigation/native" import { MyAccountEditEmailQuery } from "__generated__/MyAccountEditEmailQuery.graphql" import { MyAccountEditEmail_me$data } from "__generated__/MyAccountEditEmail_me.graphql" -import { PageWithSimpleHeader } from "app/Components/PageWithSimpleHeader" import { useToast } from "app/Components/Toast/toastHook" import { goBack } from "app/system/navigation/navigate" import { getRelayEnvironment } from "app/system/relay/defaultEnvironment" -import { useFeatureFlag } from "app/utils/hooks/useFeatureFlag" import { PlaceholderBox } from "app/utils/placeholders" import { renderWithPlaceholder } from "app/utils/renderWithPlaceholder" -import React, { Fragment, useEffect, useRef, useState } from "react" +import React, { useEffect, useRef, useState } from "react" import { createFragmentContainer, graphql, QueryRenderer, RelayProp } from "react-relay" import { string } from "yup" import { MyAccountFieldEditScreen } from "./Components/MyAccountFieldEditScreen" @@ -20,7 +18,6 @@ const MyAccountEditEmail: React.FC<{ me: MyAccountEditEmail_me$data; relay: Rela relay, }) => { const [email, setEmail] = useState(me.email ?? "") - const enableNewNavigation = useFeatureFlag("AREnableNewNavigation") const [receivedError, setReceivedError] = useState(undefined) const navigation = useNavigation() @@ -65,22 +62,9 @@ const MyAccountEditEmail: React.FC<{ me: MyAccountEditEmail_me$data; relay: Rela const toast = useToast() - const Wrapper = enableNewNavigation - ? Fragment - : ({ children }: { children: React.ReactNode }) => ( - - {children} - - ) - return ( - - + <> + - + ) } -const MyAccountEditEmailPlaceholder: React.FC<{}> = ({}) => { - const enableNewNavigation = useFeatureFlag("AREnableNewNavigation") - const Wrapper = enableNewNavigation - ? Fragment - : ({ children }: { children: React.ReactNode }) => ( - {children} - ) - - return ( - - - - ) +const MyAccountEditEmailPlaceholder: React.FC<{}> = () => { + return } export const MyAccountEditEmailContainer = createFragmentContainer(MyAccountEditEmail, { diff --git a/src/app/Scenes/MyAccount/MyAccountEditPassword.tests.tsx b/src/app/Scenes/MyAccount/MyAccountEditPassword.tests.tsx index eea1404fe7a..51dbe3da988 100644 --- a/src/app/Scenes/MyAccount/MyAccountEditPassword.tests.tsx +++ b/src/app/Scenes/MyAccount/MyAccountEditPassword.tests.tsx @@ -1,13 +1,9 @@ import { screen } from "@testing-library/react-native" -import { __globalStoreTestUtils__ } from "app/store/GlobalStore" import { renderWithWrappers } from "app/utils/tests/renderWithWrappers" import { MyAccountEditPassword } from "./MyAccountEditPassword" describe(MyAccountEditPassword, () => { jest.clearAllMocks() - __globalStoreTestUtils__?.injectFeatureFlags({ - AREnableNewNavigation: true, - }) it("has the right titles", () => { renderWithWrappers() diff --git a/src/app/Scenes/MyAccount/MyAccountEditPassword.tsx b/src/app/Scenes/MyAccount/MyAccountEditPassword.tsx index 1f1c1a83437..2a96c8fba60 100644 --- a/src/app/Scenes/MyAccount/MyAccountEditPassword.tsx +++ b/src/app/Scenes/MyAccount/MyAccountEditPassword.tsx @@ -1,14 +1,11 @@ import { Flex, Input, Separator, Text, Touchable } from "@artsy/palette-mobile" import { useNavigation } from "@react-navigation/native" import { Stack } from "app/Components/Stack" -import { MyAccountFieldEditScreen } from "app/Scenes/MyAccount/Components/MyAccountFieldEditScreen" import { getCurrentEmissionState, GlobalStore, unsafe__getEnvironment } from "app/store/GlobalStore" -import { useFeatureFlag } from "app/utils/hooks/useFeatureFlag" -import React, { Fragment, useEffect, useState } from "react" +import React, { useEffect, useState } from "react" import { Alert } from "react-native" export const MyAccountEditPassword: React.FC<{}> = ({}) => { - const enableNewNavigation = useFeatureFlag("AREnableNewNavigation") const [currentPassword, setCurrentPassword] = useState("") const [newPassword, setNewPassword] = useState("") const [passwordConfirmation, setPasswordConfirmation] = useState("") @@ -103,58 +100,42 @@ export const MyAccountEditPassword: React.FC<{}> = ({}) => { }) }, [navigation, currentPassword, newPassword, passwordConfirmation]) - const Wrapper = enableNewNavigation - ? Fragment - : ({ children }: { children: React.ReactNode }) => ( - - {children} - - ) - return ( - - - - - - - - - Password must include at least one uppercase letter, one lowercase letter, and one - number. - - - - + + + - + + + + Password must include at least one uppercase letter, one lowercase letter, and one number. + + + + + ) } diff --git a/src/app/Scenes/MyAccount/MyAccountEditPhone.tsx b/src/app/Scenes/MyAccount/MyAccountEditPhone.tsx index 921c24a5ef0..fcf09da71eb 100644 --- a/src/app/Scenes/MyAccount/MyAccountEditPhone.tsx +++ b/src/app/Scenes/MyAccount/MyAccountEditPhone.tsx @@ -3,20 +3,16 @@ import { useNavigation } from "@react-navigation/native" import { MyAccountEditPhoneQuery } from "__generated__/MyAccountEditPhoneQuery.graphql" import { MyAccountEditPhone_me$data } from "__generated__/MyAccountEditPhone_me.graphql" import { PhoneInput } from "app/Components/Input/PhoneInput/PhoneInput" -import { PageWithSimpleHeader } from "app/Components/PageWithSimpleHeader" -import { MyAccountFieldEditScreen } from "app/Scenes/MyAccount/Components/MyAccountFieldEditScreen" import { goBack } from "app/system/navigation/navigate" import { getRelayEnvironment } from "app/system/relay/defaultEnvironment" -import { useFeatureFlag } from "app/utils/hooks/useFeatureFlag" import { PlaceholderBox } from "app/utils/placeholders" import { renderWithPlaceholder } from "app/utils/renderWithPlaceholder" -import React, { Fragment, useEffect, useState } from "react" +import React, { useEffect, useState } from "react" import { createFragmentContainer, graphql, QueryRenderer } from "react-relay" import { updateMyUserProfile } from "./updateMyUserProfile" const MyAccountEditPhone: React.FC<{ me: MyAccountEditPhone_me$data }> = ({ me }) => { const navigation = useNavigation() - const enableNewNavigation = useFeatureFlag("AREnableNewNavigation") const [phone, setPhone] = useState(me.phone ?? "") const [receivedError, setReceivedError] = useState(undefined) @@ -58,42 +54,26 @@ const MyAccountEditPhone: React.FC<{ me: MyAccountEditPhone_me$data }> = ({ me } setReceivedError(e) } } - const Wrapper = enableNewNavigation - ? Fragment - : ({ children }: { children: React.ReactNode }) => ( - - {children} - - ) return ( - - - - - + + + ) } const MyAccountEditPhonePlaceholder: React.FC<{}> = ({}) => { - const enableNewNavigation = useFeatureFlag("AREnableNewNavigation") - const Wrapper = enableNewNavigation - ? Fragment - : ({ children }: { children: React.ReactNode }) => ( - {children} - ) - return ( - + <> - + ) } diff --git a/src/app/Scenes/MyAccount/MyAccountEditPriceRange.tests.tsx b/src/app/Scenes/MyAccount/MyAccountEditPriceRange.tests.tsx index d810fcacda6..1d7c949a627 100644 --- a/src/app/Scenes/MyAccount/MyAccountEditPriceRange.tests.tsx +++ b/src/app/Scenes/MyAccount/MyAccountEditPriceRange.tests.tsx @@ -1,6 +1,5 @@ import { screen } from "@testing-library/react-native" import { MyAccountEditPriceRangeTestsQuery } from "__generated__/MyAccountEditPriceRangeTestsQuery.graphql" -import { __globalStoreTestUtils__ } from "app/store/GlobalStore" import { flushPromiseQueue } from "app/utils/tests/flushPromiseQueue" import { setupTestWrapper } from "app/utils/tests/setupTestWrapper" import { graphql } from "react-relay" @@ -12,9 +11,6 @@ import { describe(MyAccountEditPriceRangeQueryRenderer, () => { beforeEach(() => { jest.clearAllMocks() - __globalStoreTestUtils__?.injectFeatureFlags({ - AREnableNewNavigation: true, - }) }) const { renderWithRelay } = setupTestWrapper({ diff --git a/src/app/Scenes/MyAccount/MyAccountEditPriceRange.tsx b/src/app/Scenes/MyAccount/MyAccountEditPriceRange.tsx index ac911fd44d3..4e38bdf093f 100644 --- a/src/app/Scenes/MyAccount/MyAccountEditPriceRange.tsx +++ b/src/app/Scenes/MyAccount/MyAccountEditPriceRange.tsx @@ -2,15 +2,12 @@ import { Flex, Text, Touchable } from "@artsy/palette-mobile" import { useNavigation } from "@react-navigation/native" import { MyAccountEditPriceRangeQuery } from "__generated__/MyAccountEditPriceRangeQuery.graphql" import { MyAccountEditPriceRange_me$data } from "__generated__/MyAccountEditPriceRange_me.graphql" -import { PageWithSimpleHeader } from "app/Components/PageWithSimpleHeader" import { Select, SelectOption } from "app/Components/Select" -import { MyAccountFieldEditScreen } from "app/Scenes/MyAccount/Components/MyAccountFieldEditScreen" import { goBack } from "app/system/navigation/navigate" import { getRelayEnvironment } from "app/system/relay/defaultEnvironment" -import { useFeatureFlag } from "app/utils/hooks/useFeatureFlag" import { PlaceholderBox } from "app/utils/placeholders" import { renderWithPlaceholder } from "app/utils/renderWithPlaceholder" -import React, { Fragment, useEffect, useState } from "react" +import React, { useEffect, useState } from "react" import { createFragmentContainer, graphql, QueryRenderer } from "react-relay" import { updateMyUserProfile } from "./updateMyUserProfile" @@ -18,7 +15,6 @@ const MyAccountEditPriceRange: React.FC<{ me: MyAccountEditPriceRange_me$data }> = ({ me }) => { const navigation = useNavigation() - const enableNewNavigation = useFeatureFlag("AREnableNewNavigation") const [receivedError, setReceivedError] = useState(undefined) const [priceRange, setPriceRange] = useState(me.priceRange ?? "") @@ -54,28 +50,9 @@ const MyAccountEditPriceRange: React.FC<{ } } - const Wrapper = enableNewNavigation - ? Fragment - : ({ children }: { children: React.ReactNode }) => ( - { - try { - await updateMyUserProfile({ priceRangeMin, priceRangeMax }) - dismiss() - } catch (e: any) { - setReceivedError(e) - } - }} - > - {children} - - ) - return ( - - + <> +