1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-11-24 02:58:09 +01:00
metamask-extension/ui/app/pages/home/home.component.js
Mark Stacey 95a95ee4bc
Refactor transaction list token filtering (#8669)
The transaction list now filters by token in the `TransactionList`
component instead of in the transaction selector. This was done in
preparation for the asset page work.

Technically this approach is slightly less efficient than before, as
we're now filtering the transactions after they've been grouped
together rather than beforehand. The difference is minimal though, and
this method is more correct.

The old filtering was broken because it inappropriately filtered out
cancel transactions. Cancel transactions always have the `to` address
set to the same as the `from` address, and the token filter only
returned transactions where the `to` address was set to the token
address.

Now that we're only filtering by the `to` address of the initial
transaction, token transaction groups will be included in their
entirety, including any cancel transactions.
2020-05-28 00:11:15 -03:00

269 lines
8.2 KiB
JavaScript

import React, { PureComponent } from 'react'
import PropTypes from 'prop-types'
import { Redirect, Route } from 'react-router-dom'
import { formatDate } from '../../helpers/utils/util'
import AssetList from '../../components/app/asset-list'
import HomeNotification from '../../components/app/home-notification'
import MultipleNotifications from '../../components/app/multiple-notifications'
import TransactionList from '../../components/app/transaction-list'
import MenuBar from '../../components/app/menu-bar'
import Popover from '../../components/ui/popover'
import Button from '../../components/ui/button'
import ConnectedSites from '../connected-sites'
import ConnectedAccounts from '../connected-accounts'
import { Tabs, Tab } from '../../components/ui/tabs'
import { EthOverview, TokenOverview } from '../../components/app/wallet-overview'
import {
RESTORE_VAULT_ROUTE,
CONFIRM_TRANSACTION_ROUTE,
CONFIRM_ADD_SUGGESTED_TOKEN_ROUTE,
INITIALIZE_BACKUP_SEED_PHRASE_ROUTE,
CONNECT_ROUTE,
CONNECTED_ROUTE,
CONNECTED_ACCOUNTS_ROUTE,
} from '../../helpers/constants/routes'
export default class Home extends PureComponent {
static contextTypes = {
t: PropTypes.func,
}
static propTypes = {
history: PropTypes.object,
forgottenPassword: PropTypes.bool,
suggestedTokens: PropTypes.object,
unconfirmedTransactionsCount: PropTypes.number,
shouldShowSeedPhraseReminder: PropTypes.bool,
isPopup: PropTypes.bool,
isNotification: PropTypes.bool.isRequired,
threeBoxSynced: PropTypes.bool,
setupThreeBox: PropTypes.func,
turnThreeBoxSyncingOn: PropTypes.func,
showRestorePrompt: PropTypes.bool,
selectedAddress: PropTypes.string,
restoreFromThreeBox: PropTypes.func,
setShowRestorePromptToFalse: PropTypes.func,
threeBoxLastUpdated: PropTypes.number,
firstPermissionsRequestId: PropTypes.string,
totalUnapprovedCount: PropTypes.number.isRequired,
setConnectedStatusPopoverHasBeenShown: PropTypes.func,
connectedStatusPopoverHasBeenShown: PropTypes.bool,
selectedToken: PropTypes.shape({
address: PropTypes.string.isRequired,
decimals: PropTypes.number,
symbol: PropTypes.string,
}),
defaultHomeActiveTabName: PropTypes.string.isRequired,
onTabClick: PropTypes.func.isRequired,
}
UNSAFE_componentWillMount () {
const {
history,
unconfirmedTransactionsCount = 0,
firstPermissionsRequestId,
} = this.props
if (firstPermissionsRequestId) {
history.push(`${CONNECT_ROUTE}/${firstPermissionsRequestId}`)
}
if (unconfirmedTransactionsCount > 0) {
history.push(CONFIRM_TRANSACTION_ROUTE)
}
}
componentDidMount () {
const {
history,
isNotification,
suggestedTokens = {},
totalUnapprovedCount,
} = this.props
if (isNotification && totalUnapprovedCount === 0) {
global.platform.closeCurrentWindow()
}
// suggested new tokens
if (Object.keys(suggestedTokens).length > 0) {
history.push(CONFIRM_ADD_SUGGESTED_TOKEN_ROUTE)
}
}
componentDidUpdate () {
const {
isNotification,
setupThreeBox,
showRestorePrompt,
threeBoxLastUpdated,
threeBoxSynced,
totalUnapprovedCount,
} = this.props
if (isNotification && totalUnapprovedCount === 0) {
global.platform.closeCurrentWindow()
}
if (threeBoxSynced && showRestorePrompt && threeBoxLastUpdated === null) {
setupThreeBox()
}
}
renderNotifications () {
const { t } = this.context
const {
history,
shouldShowSeedPhraseReminder,
isPopup,
selectedAddress,
restoreFromThreeBox,
turnThreeBoxSyncingOn,
setShowRestorePromptToFalse,
showRestorePrompt,
threeBoxLastUpdated,
} = this.props
return (
<MultipleNotifications>
{
shouldShowSeedPhraseReminder
? (
<HomeNotification
descriptionText={t('backupApprovalNotice')}
acceptText={t('backupNow')}
onAccept={() => {
if (isPopup) {
global.platform.openExtensionInBrowser(INITIALIZE_BACKUP_SEED_PHRASE_ROUTE)
} else {
history.push(INITIALIZE_BACKUP_SEED_PHRASE_ROUTE)
}
}}
infoText={t('backupApprovalInfo')}
key="home-backupApprovalNotice"
/>
)
: null
}
{
threeBoxLastUpdated && showRestorePrompt
? (
<HomeNotification
descriptionText={t('restoreWalletPreferences', [ formatDate(threeBoxLastUpdated, 'M/d/y') ])}
acceptText={t('restore')}
ignoreText={t('noThanks')}
infoText={t('dataBackupFoundInfo')}
onAccept={() => {
restoreFromThreeBox(selectedAddress)
.then(() => {
turnThreeBoxSyncingOn()
})
}}
onIgnore={() => {
setShowRestorePromptToFalse()
}}
key="home-privacyModeDefault"
/>
)
: null
}
</MultipleNotifications>
)
}
renderPopover = () => {
const { setConnectedStatusPopoverHasBeenShown } = this.props
const { t } = this.context
return (
<Popover
title={ t('whatsThis') }
onClose={setConnectedStatusPopoverHasBeenShown}
className="home__connected-status-popover"
showArrow
CustomBackground={({ onClose }) => {
return (
<div
className="home__connected-status-popover-bg-container"
onClick={onClose}
>
<div className="home__connected-status-popover-bg" />
</div>
)
}}
footer={(
<Button
type="primary"
onClick={setConnectedStatusPopoverHasBeenShown}
>
{ t('dismiss') }
</Button>
)}
>
<main className="home__connect-status-text">
<div>{ t('metaMaskConnectStatusParagraphOne') }</div>
<div>{ t('metaMaskConnectStatusParagraphTwo') }</div>
</main>
</Popover>
)
}
render () {
const {
defaultHomeActiveTabName,
onTabClick,
forgottenPassword,
history,
connectedStatusPopoverHasBeenShown,
isPopup,
selectedToken,
} = this.props
if (forgottenPassword) {
return <Redirect to={{ pathname: RESTORE_VAULT_ROUTE }} />
} else if (history.location.pathname.match(/^\/confirm-transaction/)) {
// This should only happen if this renders during the redirect to the confirm page
// Display nothing while the confirm page loads, to avoid side-effects of rendering normal home view
return null
}
const homeOverview = selectedToken
? <TokenOverview token={selectedToken} />
: <EthOverview />
return (
<div className="main-container">
<Route path={CONNECTED_ROUTE} component={ConnectedSites} exact />
<Route path={CONNECTED_ACCOUNTS_ROUTE} component={ConnectedAccounts} exact />
<div className="home__container">
{ isPopup && !connectedStatusPopoverHasBeenShown ? this.renderPopover() : null }
<div className="home__main-view">
<MenuBar />
<div className="home__balance-wrapper">
{ homeOverview }
</div>
<Tabs defaultActiveTabName={defaultHomeActiveTabName} onTabClick={onTabClick}>
<Tab
activeClassName="home__tab--active"
className="home__tab"
data-testid="home__asset-tab"
name="Assets"
>
<AssetList />
</Tab>
<Tab
activeClassName="home__tab--active"
className="home__tab"
data-testid="home__history-tab"
name="History"
>
<TransactionList tokenAddress={selectedToken?.address} />
</Tab>
</Tabs>
</div>
{ this.renderNotifications() }
</div>
</div>
)
}
}