feat: add query param to disable the nft sections of the app (#6225)

* feat: add queryparam to disable the nft sections of the app

* fix

* include mini portfolio

* add comments explaining nft disable atom usage and suggesting future work

* add subtitle exception to landing page and correct the bool

* update comment

* comment syntax nits
This commit is contained in:
Jordan Frankfurt 2023-03-27 21:54:39 -04:00 committed by GitHub
parent a0f20c54d8
commit 048607080c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 137 additions and 69 deletions

@ -6,6 +6,7 @@ import { useMGTMMicrositeEnabled } from 'featureFlags/flags/mgtm'
import { chainIdToBackendName } from 'graphql/data/util'
import { useIsNftPage } from 'hooks/useIsNftPage'
import { useIsPoolsPage } from 'hooks/useIsPoolsPage'
import { useAtomValue } from 'jotai/utils'
import { Box } from 'nft/components/Box'
import { Row } from 'nft/components/Flex'
import { UniIcon } from 'nft/components/icons'
@ -13,6 +14,7 @@ import { useProfilePageState } from 'nft/hooks'
import { ProfilePageStateType } from 'nft/types'
import { ReactNode } from 'react'
import { NavLink, NavLinkProps, useLocation, useNavigate } from 'react-router-dom'
import { shouldDisableNFTRoutesAtom } from 'state/application/atoms'
import styled from 'styled-components/macro'
import { Bag } from './Bag'
@ -60,6 +62,8 @@ export const PageTabs = () => {
const isNftPage = useIsNftPage()
const micrositeEnabled = useMGTMMicrositeEnabled()
const shouldDisableNFTRoutes = useAtomValue(shouldDisableNFTRoutesAtom)
return (
<>
<MenuItem href="/swap" isActive={pathname.startsWith('/swap')}>
@ -68,9 +72,11 @@ export const PageTabs = () => {
<MenuItem href={`/tokens/${chainName.toLowerCase()}`} isActive={pathname.startsWith('/tokens')}>
<Trans>Tokens</Trans>
</MenuItem>
<MenuItem dataTestId="nft-nav" href="/nfts" isActive={isNftPage}>
<Trans>NFTs</Trans>
</MenuItem>
{!shouldDisableNFTRoutes && (
<MenuItem dataTestId="nft-nav" href="/nfts" isActive={isNftPage}>
<Trans>NFTs</Trans>
</MenuItem>
)}
<Box display={{ sm: 'flex', lg: 'none', xxl: 'flex' }} width="full">
<MenuItem href="/pools" dataTestId="pool-nav-link" isActive={isPoolActive}>
<Trans>Pools</Trans>

@ -12,12 +12,14 @@ import { formatDelta } from 'components/Tokens/TokenDetails/PriceChart'
import Tooltip from 'components/Tooltip'
import { useGetConnection } from 'connection'
import { usePortfolioBalancesQuery } from 'graphql/data/__generated__/types-and-hooks'
import { useAtomValue } from 'jotai/utils'
import { useProfilePageState, useSellAsset, useWalletCollections } from 'nft/hooks'
import { useIsNftClaimAvailable } from 'nft/hooks/useIsNftClaimAvailable'
import { ProfilePageStateType } from 'nft/types'
import { useCallback, useState } from 'react'
import { ArrowDownRight, ArrowUpRight, Copy, CreditCard, IconProps, Info, Power, Settings } from 'react-feather'
import { useNavigate } from 'react-router-dom'
import { shouldDisableNFTRoutesAtom } from 'state/application/atoms'
import { useAppDispatch } from 'state/hooks'
import { updateSelectedWallet } from 'state/user/reducer'
import styled, { useTheme } from 'styled-components/macro'
@ -166,6 +168,8 @@ export default function AuthenticatedHeader({ account, openSettings }: { account
const clearCollectionFilters = useWalletCollections((state) => state.clearCollectionFilters)
const isClaimAvailable = useIsNftClaimAvailable((state) => state.isClaimAvailable)
const shouldDisableNFTRoutes = useAtomValue(shouldDisableNFTRoutesAtom)
const unclaimedAmount: CurrencyAmount<Token> | undefined = useUserUnclaimedAmount(account)
const isUnclaimed = useUserHasAvailableClaim(account)
const getConnection = useGetConnection()
@ -302,14 +306,16 @@ export default function AuthenticatedHeader({ account, openSettings }: { account
</>
)}
</HeaderButton>
<HeaderButton
data-testid="nft-view-self-nfts"
onClick={navigateToProfile}
size={ButtonSize.medium}
emphasis={ButtonEmphasis.medium}
>
<Trans>View and sell NFTs</Trans>
</HeaderButton>
{!shouldDisableNFTRoutes && (
<HeaderButton
data-testid="nft-view-self-nfts"
onClick={navigateToProfile}
size={ButtonSize.medium}
emphasis={ButtonEmphasis.medium}
>
<Trans>View and sell NFTs</Trans>
</HeaderButton>
)}
{Boolean(!fiatOnrampAvailable && fiatOnrampAvailabilityChecked) && (
<FiatOnrampNotAvailableText marginTop="8px">
<Trans>Not available in your region</Trans>

@ -5,7 +5,9 @@ import Column from 'components/Column'
import { AutoRow } from 'components/Row'
import { useMiniPortfolioEnabled } from 'featureFlags/flags/miniPortfolio'
import { useIsNftPage } from 'hooks/useIsNftPage'
import { useAtomValue } from 'jotai/utils'
import { useState } from 'react'
import { shouldDisableNFTRoutesAtom } from 'state/application/atoms'
import styled from 'styled-components/macro'
import { ThemedText } from 'theme'
@ -75,27 +77,31 @@ const Pages: Array<Page> = [
function MiniPortfolio({ account }: { account: string }) {
const isNftPage = useIsNftPage()
const [currentPage, setCurrentPage] = useState(isNftPage ? 1 : 0)
const shouldDisableNFTRoutes = useAtomValue(shouldDisableNFTRoutesAtom)
const Page = Pages[currentPage].component
return (
<Wrapper>
<Nav>
{Pages.map(({ title }, index) => (
<TraceEvent
events={[BrowserEvent.onClick]}
name={SharedEventName.NAVBAR_CLICKED}
element={Pages[index].loggingElementName}
key={index}
>
<NavItem
onClick={() => setCurrentPage(index)}
active={currentPage === index}
key={`Mini Portfolio page ${index}`}
{Pages.map(({ title, loggingElementName }, index) => {
if (shouldDisableNFTRoutes && loggingElementName.includes('nft')) return null
return (
<TraceEvent
events={[BrowserEvent.onClick]}
name={SharedEventName.NAVBAR_CLICKED}
element={loggingElementName}
key={index}
>
{title}
</NavItem>
</TraceEvent>
))}
<NavItem
onClick={() => setCurrentPage(index)}
active={currentPage === index}
key={`Mini Portfolio page ${index}`}
>
{title}
</NavItem>
</TraceEvent>
)
})}
</Nav>
<PageWrapper>
<Page account={account} />

@ -6,9 +6,11 @@ import TopLevelModals from 'components/TopLevelModals'
import { useFeatureFlagsIsLoaded } from 'featureFlags'
import { useMGTMMicrositeEnabled } from 'featureFlags/flags/mgtm'
import ApeModeQueryParamReader from 'hooks/useApeModeQueryParamReader'
import { useAtom } from 'jotai'
import { useBag } from 'nft/hooks/useBag'
import { lazy, Suspense, useEffect, useMemo, useState } from 'react'
import { Navigate, Route, Routes, useLocation } from 'react-router-dom'
import { Navigate, Route, Routes, useLocation, useSearchParams } from 'react-router-dom'
import { shouldDisableNFTRoutesAtom } from 'state/application/atoms'
import { StatsigProvider, StatsigUser } from 'statsig-react'
import styled from 'styled-components/macro'
import { SpinnerSVG } from 'theme/components'
@ -132,6 +134,7 @@ const LazyLoadSpinner = () => (
export default function App() {
const isLoaded = useFeatureFlagsIsLoaded()
const [shouldDisableNFTRoutes, setShouldDisableNFTRoutes] = useAtom(shouldDisableNFTRoutesAtom)
const { pathname } = useLocation()
const currentPage = getCurrentPageFromLocation(pathname)
@ -146,6 +149,15 @@ export default function App() {
setScrolledState(false)
}, [pathname])
const [searchParams] = useSearchParams()
useEffect(() => {
if (searchParams.get('disableNFTs') === 'true') {
setShouldDisableNFTRoutes(true)
} else if (searchParams.get('disableNFTs') === 'false') {
setShouldDisableNFTRoutes(false)
}
}, [searchParams, setShouldDisableNFTRoutes])
useEffect(() => {
// User properties *must* be set before sending corresponding event properties,
// so that the event contains the correct and up-to-date user properties.
@ -271,46 +283,54 @@ export default function App() {
<Route path="migrate/v2" element={<MigrateV2 />} />
<Route path="migrate/v2/:address" element={<MigrateV2Pair />} />
<Route
path="/nfts"
element={
<Suspense fallback={null}>
<NftExplore />
</Suspense>
}
/>
<Route
path="/nfts/asset/:contractAddress/:tokenId"
element={
<Suspense fallback={null}>
<Asset />
</Suspense>
}
/>
<Route
path="/nfts/profile"
element={
<Suspense fallback={null}>
<Profile />
</Suspense>
}
/>
<Route
path="/nfts/collection/:contractAddress"
element={
<Suspense fallback={null}>
<Collection />
</Suspense>
}
/>
<Route
path="/nfts/collection/:contractAddress/activity"
element={
<Suspense fallback={null}>
<Collection />
</Suspense>
}
/>
{!shouldDisableNFTRoutes && (
<>
<Route
path="/nfts"
element={
<Suspense fallback={null}>
<NftExplore />
</Suspense>
}
/>
<Route
path="/nfts/asset/:contractAddress/:tokenId"
element={
<Suspense fallback={null}>
<Asset />
</Suspense>
}
/>
<Route
path="/nfts/profile"
element={
<Suspense fallback={null}>
<Profile />
</Suspense>
}
/>
<Route
path="/nfts/collection/:contractAddress"
element={
<Suspense fallback={null}>
<Collection />
</Suspense>
}
/>
<Route
path="/nfts/collection/:contractAddress/activity"
element={
<Suspense fallback={null}>
<Collection />
</Suspense>
}
/>
</>
)}
<Route path="*" element={<Navigate to="/not-found" replace />} />
<Route path="/not-found" element={<NotFound />} />

@ -7,12 +7,14 @@ import { MAIN_CARDS, MORE_CARDS } from 'components/About/constants'
import ProtocolBanner from 'components/About/ProtocolBanner'
import { BaseButton } from 'components/Button'
import { useSwapWidgetEnabled } from 'featureFlags/flags/swapWidget'
import { useAtomValue } from 'jotai/utils'
import Swap from 'pages/Swap'
import { parse } from 'qs'
import { useEffect, useRef, useState } from 'react'
import { ArrowDownCircle } from 'react-feather'
import { useLocation, useNavigate } from 'react-router-dom'
import { Link as NativeLink } from 'react-router-dom'
import { shouldDisableNFTRoutesAtom } from 'state/application/atoms'
import { useAppSelector } from 'state/hooks'
import styled, { css } from 'styled-components/macro'
import { BREAKPOINTS } from 'theme'
@ -316,6 +318,8 @@ export default function Landing() {
}
}, [navigate, selectedWallet, queryParams.intro])
const shouldDisableNFTRoutes = useAtomValue(shouldDisableNFTRoutesAtom)
return (
<Trace page={InterfacePageName.LANDING_PAGE} shouldLogImpression>
{showContent && (
@ -342,9 +346,21 @@ export default function Landing() {
<Glow />
</GlowContainer>
<ContentContainer isDarkMode={isDarkMode}>
<TitleText isDarkMode={isDarkMode}>Trade crypto & NFTs with confidence</TitleText>
<TitleText isDarkMode={isDarkMode}>
{shouldDisableNFTRoutes ? (
<Trans>Trade crypto with confidence</Trans>
) : (
<Trans>Trade crypto and NFTs with confidence</Trans>
)}
</TitleText>
<SubTextContainer>
<SubText>Buy, sell, and explore tokens and NFTs</SubText>
<SubText>
{shouldDisableNFTRoutes ? (
<Trans>Buy, sell, and explore tokens</Trans>
) : (
<Trans>Buy, sell, and explore tokens and NFTs</Trans>
)}
</SubText>
</SubTextContainer>
<ActionsContainer>
<TraceEvent

@ -0,0 +1,14 @@
import { atomWithStorage, createJSONStorage } from 'jotai/utils'
/*
Note:
We should consider a generic sessionStorage abstraction if this pattern becomes common. (i.e., Future promo dismissals like the tax service discounts or Fiat Onramp launch notification may use this.)
This would be something similar to the current feature flag implementation, but utilizing session instead
Motivation:
some dapp browsers need to be able to disable the NFT portion of the app in order to pass Apple's app store review
this atom persists the inclusion of the `disableNFTs=boolean` query parameter via the webview's session storage
*/
const storage = createJSONStorage(() => sessionStorage)
export const shouldDisableNFTRoutesAtom = atomWithStorage('shouldDisableNFTRoutes', false, storage)