reduce layout rerenders
This commit is contained in:
parent
94d1803fa9
commit
7a661562a3
|
@ -4,7 +4,6 @@ import { useViewport } from 'hooks/useViewport'
|
|||
import BottomBar from './mobile/BottomBar'
|
||||
import { ConnectWalletButton } from './ConnectWalletButton'
|
||||
import GlobalNotification from './GlobalNotification'
|
||||
import useMangoAccount from 'hooks/useMangoAccount'
|
||||
import { abbreviateAddress } from 'utils'
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
import AccountsModal from './AccountsModal'
|
||||
|
@ -24,36 +23,20 @@ import { useWallet } from '@solana/wallet-adapter-react'
|
|||
import DepositModal from './DepositModal'
|
||||
import WithdrawModal from './WithdrawModal'
|
||||
import Tooltip from './Tooltip'
|
||||
import useMangoStore from 'stores/useMangoStore'
|
||||
|
||||
const Layout = ({ children }) => {
|
||||
const { t } = useTranslation(['common', 'delegate'])
|
||||
const { connected, publicKey } = useWallet()
|
||||
const { mangoAccount, initialLoad } = useMangoAccount()
|
||||
const [showSettingsModal, setShowSettingsModal] = useState(false)
|
||||
const [showAccountsModal, setShowAccountsModal] = useState(false)
|
||||
const [showDepositModal, setShowDepositModal] = useState(false)
|
||||
const [showWithdrawModal, setShowWithdrawModal] = useState(false)
|
||||
const [isCollapsed, setIsCollapsed] = useState(false)
|
||||
const { width } = useViewport()
|
||||
const isMobile = width ? width < breakpoints.sm : false
|
||||
const router = useRouter()
|
||||
const { pathname } = router
|
||||
const { pubkey } = router.query
|
||||
|
||||
const canWithdraw =
|
||||
mangoAccount?.owner && publicKey
|
||||
? mangoAccount?.owner?.equals(publicKey)
|
||||
: false
|
||||
|
||||
useEffect(() => {
|
||||
const collapsed = width ? width <= breakpoints.xl : false
|
||||
setIsCollapsed(collapsed)
|
||||
}, [])
|
||||
|
||||
const handleCloseAccounts = useCallback(() => {
|
||||
setShowAccountsModal(false)
|
||||
}, [])
|
||||
|
||||
const handleToggleSidebar = () => {
|
||||
setIsCollapsed(!isCollapsed)
|
||||
setTimeout(() => {
|
||||
|
@ -91,134 +74,164 @@ const Layout = ({ children }) => {
|
|||
)}
|
||||
<div className="w-full overflow-hidden">
|
||||
<GlobalNotification />
|
||||
<div className="flex h-14 items-center justify-between border-b border-th-bkg-3 bg-th-bkg-1 px-6">
|
||||
{mangoAccount && mangoAccount.beingLiquidated ? (
|
||||
<div className="flex items-center justify-center">
|
||||
<ExclamationCircleIcon className="mr-1.5 h-5 w-5 flex-shrink-0 text-th-red" />
|
||||
<span className="text-th-red">{t('being-liquidated')}</span>
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex items-center text-th-fgd-3">
|
||||
<span className="mb-0 mr-2 text-base">
|
||||
{pubkey
|
||||
? '🔎'
|
||||
: connected
|
||||
? initialLoad
|
||||
? ''
|
||||
: mangoAccount
|
||||
? '🟢'
|
||||
: '👋'
|
||||
: !isMobile
|
||||
? '🔗'
|
||||
: ''}
|
||||
</span>
|
||||
{connected || pubkey ? (
|
||||
!initialLoad ? (
|
||||
mangoAccount ? (
|
||||
<div
|
||||
className="default-transition flex items-center font-bold text-th-fgd-1 hover:text-th-fgd-3"
|
||||
role="button"
|
||||
onClick={() => setShowAccountsModal(true)}
|
||||
>
|
||||
{`${
|
||||
mangoAccount.name
|
||||
? mangoAccount.name
|
||||
: abbreviateAddress(mangoAccount.publicKey)
|
||||
}`}
|
||||
{publicKey && !mangoAccount.owner.equals(publicKey) ? (
|
||||
<Tooltip content={t('delegate:delegated-account')}>
|
||||
<UsersIcon className="ml-2 h-5 w-5 text-th-fgd-3" />
|
||||
</Tooltip>
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<span className="flex items-center text-th-fgd-3">
|
||||
{t('create-account-helper')}
|
||||
<ArrowRightIcon className="sideways-bounce ml-2 h-5 w-5 text-th-fgd-1" />
|
||||
</span>
|
||||
)
|
||||
) : (
|
||||
<div className="h-4 w-32 animate-pulse rounded bg-th-bkg-3" />
|
||||
)
|
||||
) : !isMobile ? (
|
||||
<span className="flex items-center text-th-fgd-3">
|
||||
{t('connect-helper')}
|
||||
<ArrowRightIcon className="sideways-bounce ml-2 h-5 w-5 text-th-fgd-1" />
|
||||
</span>
|
||||
) : null}
|
||||
</div>
|
||||
)}
|
||||
<div className="flex items-center space-x-4">
|
||||
{!isMobile && connected && !initialLoad ? (
|
||||
<div className="flex space-x-2">
|
||||
{mangoAccount ? (
|
||||
<Button
|
||||
className="flex h-8 w-[86px] items-center justify-center pl-3 pr-3 text-xs"
|
||||
onClick={() => setShowDepositModal(true)}
|
||||
>
|
||||
{t('deposit')}
|
||||
</Button>
|
||||
) : (
|
||||
<Button
|
||||
className="flex h-8 w-32 items-center justify-center pl-3 pr-3 text-xs"
|
||||
onClick={() => setShowAccountsModal(true)}
|
||||
>
|
||||
{t('create-account')}
|
||||
</Button>
|
||||
)}
|
||||
{canWithdraw ? (
|
||||
<Button
|
||||
className="flex h-8 w-[86px] items-center justify-center pl-3 pr-3 text-xs"
|
||||
onClick={() => setShowWithdrawModal(true)}
|
||||
primary={false}
|
||||
>
|
||||
{t('withdraw')}
|
||||
</Button>
|
||||
) : null}
|
||||
</div>
|
||||
) : null}
|
||||
<IconButton
|
||||
className="h-8 w-8"
|
||||
onClick={() => setShowSettingsModal(true)}
|
||||
>
|
||||
<CogIcon className="h-5 w-5" />
|
||||
</IconButton>
|
||||
<ConnectWalletButton />
|
||||
</div>
|
||||
</div>
|
||||
<TopBar />
|
||||
{pathname === '/' ? <FavoritesShortcutBar /> : null}
|
||||
<div className={pathname === '/' ? 'px-3' : 'px-6 pb-16 md:pb-6'}>
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{showAccountsModal && (
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const TopBar = () => {
|
||||
const { t } = useTranslation(['common', 'delegate'])
|
||||
const { connected, publicKey } = useWallet()
|
||||
const mangoAccount = useMangoStore((s) => s.selectedMangoAccount.current)
|
||||
const initialLoad = useMangoStore((s) => s.selectedMangoAccount.initialLoad)
|
||||
const router = useRouter()
|
||||
const [showAccountsModal, setShowAccountsModal] = useState(false)
|
||||
const [showSettingsModal, setShowSettingsModal] = useState(false)
|
||||
const [showDepositModal, setShowDepositModal] = useState(false)
|
||||
const [showWithdrawModal, setShowWithdrawModal] = useState(false)
|
||||
const { pubkey } = router.query
|
||||
const { width } = useViewport()
|
||||
const isMobile = width ? width < breakpoints.sm : false
|
||||
|
||||
const handleCloseAccounts = useCallback(() => {
|
||||
setShowAccountsModal(false)
|
||||
}, [])
|
||||
|
||||
const canWithdraw =
|
||||
mangoAccount?.owner && publicKey
|
||||
? mangoAccount?.owner?.equals(publicKey)
|
||||
: false
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="flex h-14 items-center justify-between border-b border-th-bkg-3 bg-th-bkg-1 px-6">
|
||||
{mangoAccount && mangoAccount.beingLiquidated ? (
|
||||
<div className="flex items-center justify-center">
|
||||
<ExclamationCircleIcon className="mr-1.5 h-5 w-5 flex-shrink-0 text-th-red" />
|
||||
<span className="text-th-red">{t('being-liquidated')}</span>
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex items-center text-th-fgd-3">
|
||||
<span className="mb-0 mr-2 text-base">
|
||||
{pubkey
|
||||
? '🔎'
|
||||
: connected
|
||||
? initialLoad
|
||||
? ''
|
||||
: mangoAccount
|
||||
? '🟢'
|
||||
: '👋'
|
||||
: !isMobile
|
||||
? '🔗'
|
||||
: ''}
|
||||
</span>
|
||||
{connected || pubkey ? (
|
||||
!initialLoad ? (
|
||||
mangoAccount ? (
|
||||
<div
|
||||
className="default-transition flex items-center font-bold text-th-fgd-1 hover:text-th-fgd-3"
|
||||
role="button"
|
||||
onClick={() => setShowAccountsModal(true)}
|
||||
>
|
||||
{`${
|
||||
mangoAccount.name
|
||||
? mangoAccount.name
|
||||
: abbreviateAddress(mangoAccount.publicKey)
|
||||
}`}
|
||||
{publicKey && !mangoAccount.owner.equals(publicKey) ? (
|
||||
<Tooltip content={t('delegate:delegated-account')}>
|
||||
<UsersIcon className="ml-2 h-5 w-5 text-th-fgd-3" />
|
||||
</Tooltip>
|
||||
) : (
|
||||
''
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
<span className="flex items-center text-th-fgd-3">
|
||||
{t('create-account-helper')}
|
||||
<ArrowRightIcon className="sideways-bounce ml-2 h-5 w-5 text-th-fgd-1" />
|
||||
</span>
|
||||
)
|
||||
) : (
|
||||
<div className="h-4 w-32 animate-pulse rounded bg-th-bkg-3" />
|
||||
)
|
||||
) : !isMobile ? (
|
||||
<span className="flex items-center text-th-fgd-3">
|
||||
{t('connect-helper')}
|
||||
<ArrowRightIcon className="sideways-bounce ml-2 h-5 w-5 text-th-fgd-1" />
|
||||
</span>
|
||||
) : null}
|
||||
</div>
|
||||
)}
|
||||
<div className="flex items-center space-x-4">
|
||||
{!isMobile && connected && !initialLoad ? (
|
||||
<div className="flex space-x-2">
|
||||
{mangoAccount ? (
|
||||
<Button
|
||||
className="flex h-8 w-[86px] items-center justify-center pl-3 pr-3 text-xs"
|
||||
onClick={() => setShowDepositModal(true)}
|
||||
>
|
||||
{t('deposit')}
|
||||
</Button>
|
||||
) : (
|
||||
<Button
|
||||
className="flex h-8 w-32 items-center justify-center pl-3 pr-3 text-xs"
|
||||
onClick={() => setShowAccountsModal(true)}
|
||||
>
|
||||
{t('create-account')}
|
||||
</Button>
|
||||
)}
|
||||
{canWithdraw ? (
|
||||
<Button
|
||||
className="flex h-8 w-[86px] items-center justify-center pl-3 pr-3 text-xs"
|
||||
onClick={() => setShowWithdrawModal(true)}
|
||||
primary={false}
|
||||
>
|
||||
{t('withdraw')}
|
||||
</Button>
|
||||
) : null}
|
||||
</div>
|
||||
) : null}
|
||||
<IconButton
|
||||
className="h-8 w-8"
|
||||
onClick={() => setShowSettingsModal(true)}
|
||||
>
|
||||
<CogIcon className="h-5 w-5" />
|
||||
</IconButton>
|
||||
<ConnectWalletButton />
|
||||
</div>
|
||||
</div>
|
||||
{showAccountsModal ? (
|
||||
<AccountsModal
|
||||
onClose={handleCloseAccounts}
|
||||
isOpen={showAccountsModal}
|
||||
/>
|
||||
)}
|
||||
) : null}
|
||||
{showSettingsModal ? (
|
||||
<SettingsModal
|
||||
onClose={() => setShowSettingsModal(false)}
|
||||
isOpen={showSettingsModal}
|
||||
/>
|
||||
) : null}
|
||||
{showDepositModal && (
|
||||
{showDepositModal ? (
|
||||
<DepositModal
|
||||
isOpen={showDepositModal}
|
||||
onClose={() => setShowDepositModal(false)}
|
||||
/>
|
||||
)}
|
||||
{showWithdrawModal && (
|
||||
) : null}
|
||||
{showWithdrawModal ? (
|
||||
<WithdrawModal
|
||||
isOpen={showWithdrawModal}
|
||||
onClose={() => setShowWithdrawModal(false)}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
) : null}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -28,11 +28,10 @@ import { abbreviateAddress } from 'utils'
|
|||
import { I80F48 } from '@blockworks-foundation/mango-client'
|
||||
import useMangoStore from 'stores/useMangoStore'
|
||||
|
||||
const I80F48_100 = I80F48.fromString('100')
|
||||
|
||||
const SideNav = ({ collapsed }) => {
|
||||
const { t } = useTranslation('common')
|
||||
const { mangoAccount } = useMangoAccount()
|
||||
const mangoGroup = useMangoStore((s) => s.selectedMangoGroup.current)
|
||||
const mangoCache = useMangoStore((s) => s.selectedMangoGroup.cache)
|
||||
const [defaultMarket] = useLocalStorageState(
|
||||
DEFAULT_MARKET_KEY,
|
||||
initialMarket
|
||||
|
@ -40,13 +39,6 @@ const SideNav = ({ collapsed }) => {
|
|||
const router = useRouter()
|
||||
const { pathname } = router
|
||||
|
||||
const I80F48_100 = I80F48.fromString('100')
|
||||
|
||||
const maintHealthRatio =
|
||||
mangoAccount && mangoGroup && mangoCache
|
||||
? mangoAccount.getHealthRatio(mangoGroup, mangoCache, 'Maint')
|
||||
: I80F48_100
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`flex flex-col justify-between transition-all duration-500 ease-in-out ${
|
||||
|
@ -188,31 +180,7 @@ const SideNav = ({ collapsed }) => {
|
|||
</ExpandableMenuItem>
|
||||
</div>
|
||||
</div>
|
||||
{mangoAccount ? (
|
||||
<div className="flex min-h-[64px] w-full items-center border-t border-th-bkg-3 ">
|
||||
<ExpandableMenuItem
|
||||
collapsed={collapsed}
|
||||
icon={<HealthHeart health={Number(maintHealthRatio)} size={32} />}
|
||||
title={
|
||||
<div className="py-3 text-left">
|
||||
<p className="mb-0 whitespace-nowrap text-xs text-th-fgd-3">
|
||||
{t('account-summary')}
|
||||
</p>
|
||||
<p className="mb-0 font-bold text-th-fgd-1">
|
||||
{abbreviateAddress(mangoAccount.publicKey)}
|
||||
</p>
|
||||
</div>
|
||||
}
|
||||
hideIconBg
|
||||
alignBottom
|
||||
>
|
||||
<AccountOverviewPopover
|
||||
collapsed={collapsed}
|
||||
health={maintHealthRatio}
|
||||
/>
|
||||
</ExpandableMenuItem>
|
||||
</div>
|
||||
) : null}
|
||||
<AccountSummaryPanel collapsed={collapsed} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
@ -293,6 +261,45 @@ const MenuItem = ({
|
|||
)
|
||||
}
|
||||
|
||||
const AccountSummaryPanel = ({ collapsed }) => {
|
||||
const { t } = useTranslation('common')
|
||||
const { mangoAccount } = useMangoAccount()
|
||||
const mangoGroup = useMangoStore((s) => s.selectedMangoGroup.current)
|
||||
const mangoCache = useMangoStore((s) => s.selectedMangoGroup.cache)
|
||||
if (!mangoAccount) return null
|
||||
|
||||
const maintHealthRatio =
|
||||
mangoAccount && mangoGroup && mangoCache
|
||||
? mangoAccount.getHealthRatio(mangoGroup, mangoCache, 'Maint')
|
||||
: I80F48_100
|
||||
|
||||
return (
|
||||
<div className="flex min-h-[64px] w-full items-center border-t border-th-bkg-3 ">
|
||||
<ExpandableMenuItem
|
||||
collapsed={collapsed}
|
||||
icon={<HealthHeart health={Number(maintHealthRatio)} size={32} />}
|
||||
title={
|
||||
<div className="py-3 text-left">
|
||||
<p className="mb-0 whitespace-nowrap text-xs text-th-fgd-3">
|
||||
{t('account-summary')}
|
||||
</p>
|
||||
<p className="mb-0 font-bold text-th-fgd-1">
|
||||
{abbreviateAddress(mangoAccount.publicKey)}
|
||||
</p>
|
||||
</div>
|
||||
}
|
||||
hideIconBg
|
||||
alignBottom
|
||||
>
|
||||
<AccountOverviewPopover
|
||||
collapsed={collapsed}
|
||||
health={maintHealthRatio}
|
||||
/>
|
||||
</ExpandableMenuItem>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const ExpandableMenuItem = ({
|
||||
children,
|
||||
collapsed,
|
||||
|
|
|
@ -15,7 +15,6 @@ import {
|
|||
actionsSelector,
|
||||
connectionSelector,
|
||||
mangoAccountSelector,
|
||||
mangoGroupSelector,
|
||||
marketConfigSelector,
|
||||
marketSelector,
|
||||
marketsSelector,
|
||||
|
@ -73,7 +72,6 @@ const useHydrateStore = () => {
|
|||
const selectedMarket = useMangoStore(marketSelector)
|
||||
const connection = useMangoStore(connectionSelector)
|
||||
const mangoAccount = useMangoStore(mangoAccountSelector)
|
||||
const mangoGroup = useMangoStore(mangoGroupSelector)
|
||||
const { wallet } = useWallet()
|
||||
|
||||
// Fetches mango group as soon as page loads
|
||||
|
@ -84,7 +82,7 @@ const useHydrateStore = () => {
|
|||
// Fetch markets info once mango group is loaded
|
||||
useEffect(() => {
|
||||
actions.fetchMarketsInfo()
|
||||
}, [mangoGroup])
|
||||
}, [actions])
|
||||
|
||||
useInterval(() => {
|
||||
actions.fetchMangoGroupCache()
|
||||
|
|
Loading…
Reference in New Issue