From 222a6d53bcf2cf33dae05393fcac704c1fd44b78 Mon Sep 17 00:00:00 2001 From: Sam Chen Date: Thu, 18 Nov 2021 14:01:45 +0800 Subject: [PATCH] perf: lazy load vote related routes (#2468) * perf: lazy load vote related routes * wrap Switch in Suspense * remove exact to match nested routes * fix nested routes * split Landing * fix --- src/pages/App.tsx | 83 ++++++------ src/pages/Vote/Landing.tsx | 257 +++++++++++++++++++++++++++++++++++++ src/pages/Vote/index.tsx | 256 +----------------------------------- 3 files changed, 310 insertions(+), 286 deletions(-) create mode 100644 src/pages/Vote/Landing.tsx diff --git a/src/pages/App.tsx b/src/pages/App.tsx index 9d8d0164d7..865eb13b80 100644 --- a/src/pages/App.tsx +++ b/src/pages/App.tsx @@ -1,5 +1,7 @@ +import Loader from 'components/Loader' import ApeModeQueryParamReader from 'hooks/useApeModeQueryParamReader' -import { Route, Switch } from 'react-router-dom' +import { lazy, Suspense } from 'react' +import { Redirect, Route, Switch } from 'react-router-dom' import styled from 'styled-components/macro' import GoogleAnalyticsReporter from '../components/analytics/GoogleAnalyticsReporter' @@ -15,7 +17,6 @@ import DarkModeQueryParamReader from '../theme/DarkModeQueryParamReader' import AddLiquidity from './AddLiquidity' import { RedirectDuplicateTokenIds } from './AddLiquidity/redirects' import { RedirectDuplicateTokenIdsV2 } from './AddLiquidityV2/redirects' -import CreateProposal from './CreateProposal' import Earn from './Earn' import Manage from './Earn/Manage' import MigrateV2 from './MigrateV2' @@ -28,8 +29,8 @@ import RemoveLiquidity from './RemoveLiquidity' import RemoveLiquidityV3 from './RemoveLiquidity/V3' import Swap from './Swap' import { OpenClaimAddressModalAndRedirectToSwap, RedirectPathToSwapOnly, RedirectToSwap } from './Swap/redirects' -import Vote from './Vote' -import VotePage from './Vote/VotePage' + +const Vote = lazy(() => import('./Vote')) const AppWrapper = styled.div` display: flex; @@ -85,46 +86,54 @@ export default function App() { - - - - - - + }> + + + + + + + + - - - + + + - - - - + + + + - - + + - + - - + + - - + + - - - + + + diff --git a/src/pages/Vote/Landing.tsx b/src/pages/Vote/Landing.tsx new file mode 100644 index 0000000000..7faf71d57c --- /dev/null +++ b/src/pages/Vote/Landing.tsx @@ -0,0 +1,257 @@ +import { Trans } from '@lingui/macro' +import { CurrencyAmount, Token } from '@uniswap/sdk-core' +import { ButtonPrimary } from 'components/Button' +import { AutoColumn } from 'components/Column' +import { CardBGImage, CardNoise, CardSection, DataCard } from 'components/earn/styled' +import FormattedCurrencyAmount from 'components/FormattedCurrencyAmount' +import Loader from 'components/Loader' +import { AutoRow, RowBetween, RowFixed } from 'components/Row' +import { SwitchLocaleLink } from 'components/SwitchLocaleLink' +import DelegateModal from 'components/vote/DelegateModal' +import ProposalEmptyState from 'components/vote/ProposalEmptyState' +import { useActiveWeb3React } from 'hooks/web3' +import JSBI from 'jsbi' +import { darken } from 'polished' +import { Link } from 'react-router-dom' +import { Button } from 'rebass/styled-components' +import { useModalOpen, useToggleDelegateModal } from 'state/application/hooks' +import { ApplicationModal } from 'state/application/reducer' +import { ProposalData } from 'state/governance/hooks' +import { useAllProposalData, useUserDelegatee, useUserVotes } from 'state/governance/hooks' +import { useTokenBalance } from 'state/wallet/hooks' +import styled from 'styled-components/macro' +import { ExternalLink, TYPE } from 'theme' +import { shortenAddress } from 'utils' +import { ExplorerDataType, getExplorerLink } from 'utils/getExplorerLink' + +import { ZERO_ADDRESS } from '../../constants/misc' +import { UNI } from '../../constants/tokens' +import { ProposalStatus } from './styled' + +const PageWrapper = styled(AutoColumn)`` + +const TopSection = styled(AutoColumn)` + max-width: 640px; + width: 100%; +` + +const Proposal = styled(Button)` + padding: 0.75rem 1rem; + width: 100%; + margin-top: 1rem; + border-radius: 12px; + display: grid; + grid-template-columns: 48px 1fr 120px; + align-items: center; + text-align: left; + outline: none; + cursor: pointer; + color: ${({ theme }) => theme.text1}; + text-decoration: none; + background-color: ${({ theme }) => theme.bg1}; + &:focus { + background-color: ${({ theme }) => darken(0.05, theme.bg1)}; + } + &:hover { + background-color: ${({ theme }) => darken(0.05, theme.bg1)}; + } +` + +const ProposalNumber = styled.span` + opacity: 0.6; +` + +const ProposalTitle = styled.span` + font-weight: 600; +` + +const VoteCard = styled(DataCard)` + background: radial-gradient(76.02% 75.41% at 1.84% 0%, #27ae60 0%, #000000 100%); + overflow: hidden; +` + +const WrapSmall = styled(RowBetween)` + margin-bottom: 1rem; + ${({ theme }) => theme.mediaWidth.upToSmall` + flex-wrap: wrap; + `}; +` + +const TextButton = styled(TYPE.main)` + color: ${({ theme }) => theme.primary1}; + :hover { + cursor: pointer; + text-decoration: underline; + } +` + +const AddressButton = styled.div` + border: 1px solid ${({ theme }) => theme.bg3}; + padding: 2px 4px; + border-radius: 8px; + display: flex; + justify-content: center; + align-items: center; +` + +const StyledExternalLink = styled(ExternalLink)` + color: ${({ theme }) => theme.text1}; +` + +export default function Landing() { + const { account, chainId } = useActiveWeb3React() + + // toggle for showing delegation modal + const showDelegateModal = useModalOpen(ApplicationModal.DELEGATE) + const toggleDelegateModal = useToggleDelegateModal() + + // get data to list all proposals + const { data: allProposals, loading: loadingProposals } = useAllProposalData() + + // user data + const { loading: loadingAvailableVotes, votes: availableVotes } = useUserVotes() + const uniBalance: CurrencyAmount | undefined = useTokenBalance( + account ?? undefined, + chainId ? UNI[chainId] : undefined + ) + const userDelegatee: string | undefined = useUserDelegatee() + + // show delegation option if they have have a balance, but have not delegated + const showUnlockVoting = Boolean( + uniBalance && JSBI.notEqual(uniBalance.quotient, JSBI.BigInt(0)) && userDelegatee === ZERO_ADDRESS + ) + return ( + <> + + Unlock Votes : Update Delegation} + /> + + + + + + + + + Uniswap Governance + + + + + + UNI tokens represent voting shares in Uniswap governance. You can vote on each proposal yourself + or delegate your votes to a third party. + + + + + + Read more about Uniswap governance + + + + + + + + + + + + Proposals + + + {loadingProposals || loadingAvailableVotes ? : null} + {showUnlockVoting ? ( + + Unlock Voting + + ) : availableVotes && JSBI.notEqual(JSBI.BigInt(0), availableVotes?.quotient) ? ( + + + Votes + + + ) : uniBalance && + userDelegatee && + userDelegatee !== ZERO_ADDRESS && + JSBI.notEqual(JSBI.BigInt(0), uniBalance?.quotient) ? ( + + + Votes + + + ) : ( + '' + )} + + Create Proposal + + + + {!showUnlockVoting && ( + +
+ {userDelegatee && userDelegatee !== ZERO_ADDRESS ? ( + + + Delegated to: + + + + {userDelegatee === account ? Self : shortenAddress(userDelegatee)} + + + (edit) + + + + ) : ( + '' + )} + + )} + {allProposals?.length === 0 && } + {allProposals + ?.slice(0) + ?.reverse() + ?.map((p: ProposalData) => { + return ( + + + {p.governorIndex}.{p.id} + + {p.title} + + + ) + })} + + + A minimum threshold of 0.25% of the total UNI supply is required to submit proposals + + + + + ) +} diff --git a/src/pages/Vote/index.tsx b/src/pages/Vote/index.tsx index 9c0cd455c0..1e49d34b13 100644 --- a/src/pages/Vote/index.tsx +++ b/src/pages/Vote/index.tsx @@ -1,257 +1,15 @@ -import { Trans } from '@lingui/macro' -import { CurrencyAmount, Token } from '@uniswap/sdk-core' -import { ButtonPrimary } from 'components/Button' -import { AutoColumn } from 'components/Column' -import { CardBGImage, CardNoise, CardSection, DataCard } from 'components/earn/styled' -import FormattedCurrencyAmount from 'components/FormattedCurrencyAmount' -import Loader from 'components/Loader' -import { AutoRow, RowBetween, RowFixed } from 'components/Row' -import { SwitchLocaleLink } from 'components/SwitchLocaleLink' -import DelegateModal from 'components/vote/DelegateModal' -import ProposalEmptyState from 'components/vote/ProposalEmptyState' -import { useActiveWeb3React } from 'hooks/web3' -import JSBI from 'jsbi' -import { darken } from 'polished' -import { Link } from 'react-router-dom' -import { Button } from 'rebass/styled-components' -import { useModalOpen, useToggleDelegateModal } from 'state/application/hooks' -import { ApplicationModal } from 'state/application/reducer' -import { ProposalData, useAllProposalData, useUserDelegatee, useUserVotes } from 'state/governance/hooks' -import { useTokenBalance } from 'state/wallet/hooks' -import styled from 'styled-components/macro' -import { ExternalLink, TYPE } from 'theme' -import { shortenAddress } from 'utils' -import { ExplorerDataType, getExplorerLink } from 'utils/getExplorerLink' +import CreateProposal from 'pages/CreateProposal' +import { Route } from 'react-router-dom' -import { ZERO_ADDRESS } from '../../constants/misc' -import { UNI } from '../../constants/tokens' -import { ProposalStatus } from './styled' - -const PageWrapper = styled(AutoColumn)`` - -const TopSection = styled(AutoColumn)` - max-width: 640px; - width: 100%; -` - -const Proposal = styled(Button)` - padding: 0.75rem 1rem; - width: 100%; - margin-top: 1rem; - border-radius: 12px; - display: grid; - grid-template-columns: 48px 1fr 120px; - align-items: center; - text-align: left; - outline: none; - cursor: pointer; - color: ${({ theme }) => theme.text1}; - text-decoration: none; - background-color: ${({ theme }) => theme.bg1}; - &:focus { - background-color: ${({ theme }) => darken(0.05, theme.bg1)}; - } - &:hover { - background-color: ${({ theme }) => darken(0.05, theme.bg1)}; - } -` - -const ProposalNumber = styled.span` - opacity: 0.6; -` - -const ProposalTitle = styled.span` - font-weight: 600; -` - -const VoteCard = styled(DataCard)` - background: radial-gradient(76.02% 75.41% at 1.84% 0%, #27ae60 0%, #000000 100%); - overflow: hidden; -` - -const WrapSmall = styled(RowBetween)` - margin-bottom: 1rem; - ${({ theme }) => theme.mediaWidth.upToSmall` - flex-wrap: wrap; - `}; -` - -const TextButton = styled(TYPE.main)` - color: ${({ theme }) => theme.primary1}; - :hover { - cursor: pointer; - text-decoration: underline; - } -` - -const AddressButton = styled.div` - border: 1px solid ${({ theme }) => theme.bg3}; - padding: 2px 4px; - border-radius: 8px; - display: flex; - justify-content: center; - align-items: center; -` - -const StyledExternalLink = styled(ExternalLink)` - color: ${({ theme }) => theme.text1}; -` +import Landing from './Landing' +import VotePage from './VotePage' export default function Vote() { - const { account, chainId } = useActiveWeb3React() - - // toggle for showing delegation modal - const showDelegateModal = useModalOpen(ApplicationModal.DELEGATE) - const toggleDelegateModal = useToggleDelegateModal() - - // get data to list all proposals - const { data: allProposals, loading: loadingProposals } = useAllProposalData() - - // user data - const { loading: loadingAvailableVotes, votes: availableVotes } = useUserVotes() - const uniBalance: CurrencyAmount | undefined = useTokenBalance( - account ?? undefined, - chainId ? UNI[chainId] : undefined - ) - const userDelegatee: string | undefined = useUserDelegatee() - - // show delegation option if they have have a balance, but have not delegated - const showUnlockVoting = Boolean( - uniBalance && JSBI.notEqual(uniBalance.quotient, JSBI.BigInt(0)) && userDelegatee === ZERO_ADDRESS - ) - return ( <> - - Unlock Votes : Update Delegation} - /> - - - - - - - - - Uniswap Governance - - - - - - UNI tokens represent voting shares in Uniswap governance. You can vote on each proposal yourself - or delegate your votes to a third party. - - - - - - Read more about Uniswap governance - - - - - - - - - - - - Proposals - - - {loadingProposals || loadingAvailableVotes ? : null} - {showUnlockVoting ? ( - - Unlock Voting - - ) : availableVotes && JSBI.notEqual(JSBI.BigInt(0), availableVotes?.quotient) ? ( - - - Votes - - - ) : uniBalance && - userDelegatee && - userDelegatee !== ZERO_ADDRESS && - JSBI.notEqual(JSBI.BigInt(0), uniBalance?.quotient) ? ( - - - Votes - - - ) : ( - '' - )} - - Create Proposal - - - - {!showUnlockVoting && ( - -
- {userDelegatee && userDelegatee !== ZERO_ADDRESS ? ( - - - Delegated to: - - - - {userDelegatee === account ? Self : shortenAddress(userDelegatee)} - - - (edit) - - - - ) : ( - '' - )} - - )} - {allProposals?.length === 0 && } - {allProposals - ?.slice(0) - ?.reverse() - ?.map((p: ProposalData) => { - return ( - - - {p.governorIndex}.{p.id} - - {p.title} - - - ) - })} - - - A minimum threshold of 0.25% of the total UNI supply is required to submit proposals - - - + + + ) }