feat: add loading indicator to activity tab in mini portfolio (#6754)
* feat: add loading indicator to activity tab in mini portfolio * should not render spinner when activity key is active * add an unread notification dot that is dismissed when the user visits the activity tab * pr feedback
This commit is contained in:
parent
7a3c51bc90
commit
c2a83cabaa
@ -2,12 +2,14 @@ import { Trans } from '@lingui/macro'
|
||||
import { Trace, TraceEvent } from '@uniswap/analytics'
|
||||
import { BrowserEvent, InterfaceElementName, InterfaceSectionName, SharedEventName } from '@uniswap/analytics-events'
|
||||
import Column from 'components/Column'
|
||||
import { LoaderV2 } from 'components/Icons/LoadingSpinner'
|
||||
import { AutoRow } from 'components/Row'
|
||||
import { useIsNftPage } from 'hooks/useIsNftPage'
|
||||
import { useAtomValue } from 'jotai/utils'
|
||||
import { useState } from 'react'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { shouldDisableNFTRoutesAtom } from 'state/application/atoms'
|
||||
import styled from 'styled-components/macro'
|
||||
import { useHasPendingTransactions } from 'state/transactions/hooks'
|
||||
import styled, { useTheme } from 'styled-components/macro'
|
||||
import { ThemedText } from 'theme'
|
||||
|
||||
import { ActivityTab } from './Activity'
|
||||
@ -35,12 +37,15 @@ const Nav = styled(AutoRow)`
|
||||
`
|
||||
|
||||
const NavItem = styled(ThemedText.SubHeader)<{ active?: boolean }>`
|
||||
align-items: center;
|
||||
color: ${({ theme, active }) => (active ? theme.textPrimary : theme.textTertiary)};
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
transition: ${({ theme }) => `${theme.transition.duration.medium} ${theme.transition.timing.ease} color`};
|
||||
|
||||
&:hover {
|
||||
${({ theme, active }) => !active && `color: ${theme.textSecondary}`};
|
||||
cursor: pointer;
|
||||
}
|
||||
`
|
||||
|
||||
@ -88,16 +93,31 @@ const Pages: Array<Page> = [
|
||||
|
||||
export default function MiniPortfolio({ account }: { account: string }) {
|
||||
const isNftPage = useIsNftPage()
|
||||
const theme = useTheme()
|
||||
const [currentPage, setCurrentPage] = useState(isNftPage ? 1 : 0)
|
||||
const [activityUnread, setActivityUnread] = useState(false)
|
||||
const shouldDisableNFTRoutes = useAtomValue(shouldDisableNFTRoutesAtom)
|
||||
|
||||
const Page = Pages[currentPage].component
|
||||
const { component: Page, key: currentKey } = Pages[currentPage]
|
||||
|
||||
const hasPendingTransactions = useHasPendingTransactions()
|
||||
|
||||
useEffect(() => {
|
||||
if (hasPendingTransactions && currentKey !== 'activity') setActivityUnread(true)
|
||||
}, [currentKey, hasPendingTransactions])
|
||||
|
||||
return (
|
||||
<Trace section={InterfaceSectionName.MINI_PORTFOLIO}>
|
||||
<Wrapper>
|
||||
<Nav data-testid="mini-portfolio-navbar">
|
||||
{Pages.map(({ title, loggingElementName, key }, index) => {
|
||||
if (shouldDisableNFTRoutes && loggingElementName.includes('nft')) return null
|
||||
const isUnselectedActivity = key === 'activity' && currentKey !== 'activity'
|
||||
const showActivityIndicator = isUnselectedActivity && (hasPendingTransactions || activityUnread)
|
||||
const handleNavItemClick = () => {
|
||||
setCurrentPage(index)
|
||||
if (key === 'activity') setActivityUnread(false)
|
||||
}
|
||||
return (
|
||||
<TraceEvent
|
||||
events={[BrowserEvent.onClick]}
|
||||
@ -105,8 +125,20 @@ export default function MiniPortfolio({ account }: { account: string }) {
|
||||
element={loggingElementName}
|
||||
key={index}
|
||||
>
|
||||
<NavItem onClick={() => setCurrentPage(index)} active={currentPage === index} key={key}>
|
||||
{title}
|
||||
<NavItem onClick={handleNavItemClick} active={currentPage === index} key={key}>
|
||||
<span>{title}</span>
|
||||
{showActivityIndicator && (
|
||||
<>
|
||||
|
||||
{hasPendingTransactions ? (
|
||||
<LoaderV2 />
|
||||
) : (
|
||||
<svg width="8" height="8" viewBox="0 0 8 8" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<circle cx="4" cy="4" r="4" fill={theme.accentAction} />
|
||||
</svg>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</NavItem>
|
||||
</TraceEvent>
|
||||
)
|
||||
|
@ -125,3 +125,10 @@ export function useHasPendingApproval(token?: Token, spender?: string): boolean
|
||||
export function useHasPendingRevocation(token?: Token, spender?: string): boolean {
|
||||
return usePendingApprovalAmount(token, spender)?.eq(0) ?? false
|
||||
}
|
||||
|
||||
export function useHasPendingTransactions() {
|
||||
const allTransactions = useAllTransactions()
|
||||
return useMemo(() => {
|
||||
return Object.values(allTransactions).filter((tx) => !tx.receipt).length > 0
|
||||
}, [allTransactions])
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user