1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-12-23 01:39:44 +01:00
metamask-extension/ui/pages/home/home.component.js
Nidhi Kumari b8b94c2c1f
UX Multichain: Added balance-overview component (#20528)
* added balance-overview component

* updated balance overview component to use Currency utility props

* added MULTICHAIN feature flag

* lint fix

* lint fix

* lint fix

* updated ternary operators
2023-08-29 22:07:23 +05:30

1015 lines
34 KiB
JavaScript

import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import { Redirect, Route } from 'react-router-dom';
import {
///: BEGIN:ONLY_INCLUDE_IN(build-main)
MetaMetricsContextProp,
///: END:ONLY_INCLUDE_IN
MetaMetricsEventCategory,
MetaMetricsEventName,
} from '../../../shared/constants/metametrics';
import AssetList from '../../components/app/asset-list';
///: BEGIN:ONLY_INCLUDE_IN(build-main,build-beta,build-flask)
import NftsTab from '../../components/app/nfts-tab';
import TermsOfUsePopup from '../../components/app/terms-of-use-popup';
import RecoveryPhraseReminder from '../../components/app/recovery-phrase-reminder';
///: END:ONLY_INCLUDE_IN
import HomeNotification from '../../components/app/home-notification';
import MultipleNotifications from '../../components/app/multiple-notifications';
import TransactionList from '../../components/app/transaction-list';
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 } from '../../components/app/wallet-overview';
import WhatsNewPopup from '../../components/app/whats-new-popup';
import ActionableMessage from '../../components/ui/actionable-message/actionable-message';
import {
FontWeight,
Display,
TextColor,
TextVariant,
///: BEGIN:ONLY_INCLUDE_IN(build-main)
Size,
///: END:ONLY_INCLUDE_IN
///: BEGIN:ONLY_INCLUDE_IN(build-main,build-mmi)
JustifyContent,
///: END:ONLY_INCLUDE_IN
} from '../../helpers/constants/design-system';
import { SECOND } from '../../../shared/constants/time';
import {
ButtonIcon,
ButtonIconSize,
IconName,
Box,
///: BEGIN:ONLY_INCLUDE_IN(build-main)
ButtonLink,
///: END:ONLY_INCLUDE_IN
Text,
} from '../../components/component-library';
import {
ASSET_ROUTE,
RESTORE_VAULT_ROUTE,
CONFIRM_TRANSACTION_ROUTE,
CONFIRM_ADD_SUGGESTED_TOKEN_ROUTE,
CONFIRM_ADD_SUGGESTED_NFT_ROUTE,
CONNECT_ROUTE,
CONNECTED_ROUTE,
CONNECTED_ACCOUNTS_ROUTE,
AWAITING_SWAP_ROUTE,
BUILD_QUOTE_ROUTE,
VIEW_QUOTE_ROUTE,
CONFIRMATION_V_NEXT_ROUTE,
///: BEGIN:ONLY_INCLUDE_IN(build-main,build-beta,build-flask)
ONBOARDING_SECURE_YOUR_WALLET_ROUTE,
///: END:ONLY_INCLUDE_IN
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
CONFIRM_ADD_CUSTODIAN_TOKEN,
INTERACTIVE_REPLACEMENT_TOKEN_PAGE,
///: END:ONLY_INCLUDE_IN
} from '../../helpers/constants/routes';
import ZENDESK_URLS from '../../helpers/constants/zendesk-url';
///: BEGIN:ONLY_INCLUDE_IN(build-main)
import { SUPPORT_LINK } from '../../../shared/lib/ui-utils';
///: END:ONLY_INCLUDE_IN
///: BEGIN:ONLY_INCLUDE_IN(build-beta)
import BetaHomeFooter from './beta/beta-home-footer.component';
///: END:ONLY_INCLUDE_IN
///: BEGIN:ONLY_INCLUDE_IN(build-flask)
import FlaskHomeFooter from './flask/flask-home-footer.component';
///: END:ONLY_INCLUDE_IN
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
import InstitutionalHomeFooter from './institutional/institutional-home-footer';
///: END:ONLY_INCLUDE_IN
function shouldCloseNotificationPopup({
isNotification,
totalUnapprovedCount,
hasApprovalFlows,
isSigningQRHardwareTransaction,
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
waitForConfirmDeepLinkDialog,
institutionalConnectRequests,
///: END:ONLY_INCLUDE_IN
}) {
let shouldCLose =
isNotification &&
totalUnapprovedCount === 0 &&
!hasApprovalFlows &&
!isSigningQRHardwareTransaction;
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
shouldCLose &&=
// MMI User must be shown a deeplink
!waitForConfirmDeepLinkDialog &&
// MMI User is connecting to custodian
institutionalConnectRequests.length === 0;
///: END:ONLY_INCLUDE_IN
return shouldCLose;
}
export default class Home extends PureComponent {
static contextTypes = {
t: PropTypes.func,
trackEvent: PropTypes.func,
};
static propTypes = {
history: PropTypes.object,
forgottenPassword: PropTypes.bool,
hasTransactionPendingApprovals: PropTypes.bool.isRequired,
hasWatchTokenPendingApprovals: PropTypes.bool,
hasWatchNftPendingApprovals: PropTypes.bool,
///: BEGIN:ONLY_INCLUDE_IN(build-main,build-beta,build-flask)
shouldShowSeedPhraseReminder: PropTypes.bool.isRequired,
isPopup: PropTypes.bool,
connectedStatusPopoverHasBeenShown: PropTypes.bool,
showRecoveryPhraseReminder: PropTypes.bool.isRequired,
showTermsOfUsePopup: PropTypes.bool.isRequired,
seedPhraseBackedUp: (props) => {
if (
props.seedPhraseBackedUp !== null &&
typeof props.seedPhraseBackedUp !== 'boolean'
) {
throw new Error(
`seedPhraseBackedUp is required to be null or boolean. Received ${props.seedPhraseBackedUp}`,
);
}
},
///: END:ONLY_INCLUDE_IN
isNotification: PropTypes.bool.isRequired,
firstPermissionsRequestId: PropTypes.string,
// This prop is used in the `shouldCloseNotificationPopup` function
// eslint-disable-next-line react/no-unused-prop-types
totalUnapprovedCount: PropTypes.number.isRequired,
setConnectedStatusPopoverHasBeenShown: PropTypes.func,
defaultHomeActiveTabName: PropTypes.string,
firstTimeFlowType: PropTypes.string,
completedOnboarding: PropTypes.bool,
onTabClick: PropTypes.func.isRequired,
haveSwapsQuotes: PropTypes.bool.isRequired,
showAwaitingSwapScreen: PropTypes.bool.isRequired,
swapsFetchParams: PropTypes.object,
location: PropTypes.object,
shouldShowWeb3ShimUsageNotification: PropTypes.bool.isRequired,
setWeb3ShimUsageAlertDismissed: PropTypes.func.isRequired,
originOfCurrentTab: PropTypes.string,
disableWeb3ShimUsageAlert: PropTypes.func.isRequired,
pendingConfirmations: PropTypes.arrayOf(PropTypes.object).isRequired,
hasApprovalFlows: PropTypes.bool.isRequired,
infuraBlocked: PropTypes.bool.isRequired,
showWhatsNewPopup: PropTypes.bool.isRequired,
hideWhatsNewPopup: PropTypes.func.isRequired,
announcementsToShow: PropTypes.bool.isRequired,
///: BEGIN:ONLY_INCLUDE_IN(snaps)
errorsToShow: PropTypes.object.isRequired,
shouldShowErrors: PropTypes.bool.isRequired,
removeSnapError: PropTypes.func.isRequired,
///: END:ONLY_INCLUDE_IN
setRecoveryPhraseReminderHasBeenShown: PropTypes.func.isRequired,
setRecoveryPhraseReminderLastShown: PropTypes.func.isRequired,
setTermsOfUseLastAgreed: PropTypes.func.isRequired,
showOutdatedBrowserWarning: PropTypes.bool.isRequired,
setOutdatedBrowserWarningLastShown: PropTypes.func.isRequired,
newNetworkAddedName: PropTypes.string,
// This prop is used in the `shouldCloseNotificationPopup` function
// eslint-disable-next-line react/no-unused-prop-types
isSigningQRHardwareTransaction: PropTypes.bool.isRequired,
newNftAddedMessage: PropTypes.string,
setNewNftAddedMessage: PropTypes.func.isRequired,
removeNftMessage: PropTypes.string,
setRemoveNftMessage: PropTypes.func.isRequired,
closeNotificationPopup: PropTypes.func.isRequired,
newTokensImported: PropTypes.string,
setNewTokensImported: PropTypes.func.isRequired,
newNetworkAddedConfigurationId: PropTypes.string,
clearNewNetworkAdded: PropTypes.func,
setActiveNetwork: PropTypes.func,
onboardedInThisUISession: PropTypes.bool,
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
institutionalConnectRequests: PropTypes.arrayOf(PropTypes.object),
mmiPortfolioEnabled: PropTypes.bool,
mmiPortfolioUrl: PropTypes.string,
modalOpen: PropTypes.bool,
setWaitForConfirmDeepLinkDialog: PropTypes.func,
waitForConfirmDeepLinkDialog: PropTypes.bool,
///: END:ONLY_INCLUDE_IN
};
state = {
canShowBlockageNotification: true,
notificationClosing: false,
redirecting: false,
};
constructor(props) {
super(props);
const {
closeNotificationPopup,
firstPermissionsRequestId,
haveSwapsQuotes,
isNotification,
showAwaitingSwapScreen,
hasWatchTokenPendingApprovals,
hasWatchNftPendingApprovals,
swapsFetchParams,
hasTransactionPendingApprovals,
location,
} = this.props;
const stayOnHomePage = Boolean(location?.state?.stayOnHomePage);
if (shouldCloseNotificationPopup(props)) {
this.state.notificationClosing = true;
closeNotificationPopup();
} else if (
firstPermissionsRequestId ||
hasTransactionPendingApprovals ||
hasWatchTokenPendingApprovals ||
hasWatchNftPendingApprovals ||
(!isNotification &&
!stayOnHomePage &&
(showAwaitingSwapScreen || haveSwapsQuotes || swapsFetchParams))
) {
this.state.redirecting = true;
}
}
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
checkInstitutionalConnectRequest() {
const { history, institutionalConnectRequests } = this.props;
if (
institutionalConnectRequests &&
institutionalConnectRequests.length > 0 &&
institutionalConnectRequests[0].feature === 'custodian'
) {
if (
institutionalConnectRequests[0].method ===
'metamaskinstitutional_reauthenticate'
) {
history.push(INTERACTIVE_REPLACEMENT_TOKEN_PAGE);
} else if (
institutionalConnectRequests[0].method ===
'metamaskinstitutional_authenticate'
) {
history.push(CONFIRM_ADD_CUSTODIAN_TOKEN);
}
}
}
shouldCloseCurrentWindow() {
const {
isNotification,
modalOpen,
totalUnapprovedCount,
institutionalConnectRequests,
waitForConfirmDeepLinkDialog,
} = this.props;
if (
isNotification &&
totalUnapprovedCount === 0 &&
institutionalConnectRequests.length === 0 &&
!waitForConfirmDeepLinkDialog &&
!modalOpen
) {
global.platform.closeCurrentWindow();
}
}
///: END:ONLY_INCLUDE_IN
checkStatusAndNavigate() {
const {
firstPermissionsRequestId,
history,
isNotification,
hasTransactionPendingApprovals,
hasWatchTokenPendingApprovals,
hasWatchNftPendingApprovals,
haveSwapsQuotes,
showAwaitingSwapScreen,
swapsFetchParams,
location,
pendingConfirmations,
hasApprovalFlows,
} = this.props;
const stayOnHomePage = Boolean(location?.state?.stayOnHomePage);
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
this.shouldCloseCurrentWindow();
///: END:ONLY_INCLUDE_IN
const canRedirect = !isNotification && !stayOnHomePage;
if (canRedirect && showAwaitingSwapScreen) {
history.push(AWAITING_SWAP_ROUTE);
} else if (canRedirect && haveSwapsQuotes) {
history.push(VIEW_QUOTE_ROUTE);
} else if (canRedirect && swapsFetchParams) {
history.push(BUILD_QUOTE_ROUTE);
} else if (firstPermissionsRequestId) {
history.push(`${CONNECT_ROUTE}/${firstPermissionsRequestId}`);
} else if (hasTransactionPendingApprovals) {
history.push(CONFIRM_TRANSACTION_ROUTE);
} else if (hasWatchTokenPendingApprovals) {
history.push(CONFIRM_ADD_SUGGESTED_TOKEN_ROUTE);
} else if (hasWatchNftPendingApprovals) {
history.push(CONFIRM_ADD_SUGGESTED_NFT_ROUTE);
} else if (pendingConfirmations.length > 0 || hasApprovalFlows) {
history.push(CONFIRMATION_V_NEXT_ROUTE);
}
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
this.checkInstitutionalConnectRequest();
///: END:ONLY_INCLUDE_IN
}
componentDidMount() {
this.checkStatusAndNavigate();
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
const { setWaitForConfirmDeepLinkDialog } = this.props;
window.addEventListener('beforeunload', () => {
// If user closes notification window manually, change waitForConfirmDeepLinkDialog to false
setWaitForConfirmDeepLinkDialog(false);
});
///: END:ONLY_INCLUDE_IN
}
static getDerivedStateFromProps(props) {
if (shouldCloseNotificationPopup(props)) {
return { notificationClosing: true };
}
return null;
}
componentDidUpdate(_prevProps, prevState) {
const { closeNotificationPopup, isNotification } = this.props;
const { notificationClosing } = this.state;
if (notificationClosing && !prevState.notificationClosing) {
closeNotificationPopup();
} else if (isNotification) {
this.checkStatusAndNavigate();
}
}
onRecoveryPhraseReminderClose = () => {
const {
setRecoveryPhraseReminderHasBeenShown,
setRecoveryPhraseReminderLastShown,
} = this.props;
setRecoveryPhraseReminderHasBeenShown(true);
setRecoveryPhraseReminderLastShown(new Date().getTime());
};
onAcceptTermsOfUse = () => {
const { setTermsOfUseLastAgreed } = this.props;
setTermsOfUseLastAgreed(new Date().getTime());
this.context.trackEvent({
category: MetaMetricsEventCategory.Onboarding,
event: MetaMetricsEventName.TermsOfUseAccepted,
properties: {
location: 'Terms Of Use Popover',
},
});
};
///: BEGIN:ONLY_INCLUDE_IN(build-main)
onSupportLinkClick = () => {
this.context.trackEvent(
{
category: MetaMetricsEventCategory.Home,
event: MetaMetricsEventName.SupportLinkClicked,
properties: {
url: SUPPORT_LINK,
},
},
{
contextPropsIntoEventProperties: [MetaMetricsContextProp.PageTitle],
},
);
};
///: END:ONLY_INCLUDE_IN
onOutdatedBrowserWarningClose = () => {
const { setOutdatedBrowserWarningLastShown } = this.props;
setOutdatedBrowserWarningLastShown(new Date().getTime());
};
renderNotifications() {
const { t } = this.context;
const {
///: BEGIN:ONLY_INCLUDE_IN(build-main,build-beta,build-flask)
history,
shouldShowSeedPhraseReminder,
isPopup,
///: END:ONLY_INCLUDE_IN
shouldShowWeb3ShimUsageNotification,
setWeb3ShimUsageAlertDismissed,
originOfCurrentTab,
disableWeb3ShimUsageAlert,
///: BEGIN:ONLY_INCLUDE_IN(snaps)
removeSnapError,
errorsToShow,
shouldShowErrors,
///: END:ONLY_INCLUDE_IN
infuraBlocked,
showOutdatedBrowserWarning,
newNftAddedMessage,
setNewNftAddedMessage,
newNetworkAddedName,
removeNftMessage,
setRemoveNftMessage,
newTokensImported,
setNewTokensImported,
newNetworkAddedConfigurationId,
clearNewNetworkAdded,
setActiveNetwork,
} = this.props;
const onAutoHide = () => {
setNewNftAddedMessage('');
setRemoveNftMessage('');
};
const autoHideDelay = 5 * SECOND;
return (
<MultipleNotifications>
{
///: BEGIN:ONLY_INCLUDE_IN(snaps)
shouldShowErrors
? Object.entries(errorsToShow).map(([errorId, error]) => {
return (
<HomeNotification
classNames={['home__error-message']}
infoText={error.data.snapId}
descriptionText={
<>
<Text
variant={TextVariant.bodyMd}
as="h5"
color={TextColor.textAlternative}
>
{t('somethingWentWrong')}
</Text>
<Text
color={TextColor.textAlternative}
variant={TextVariant.bodySm}
as="h6"
>
{t('snapError', [error.message, error.code])}
</Text>
</>
}
onIgnore={async () => {
await removeSnapError(errorId);
}}
ignoreText="Dismiss"
key="home-error-message"
/>
);
})
: null
///: END:ONLY_INCLUDE_IN
}
{newNftAddedMessage === 'success' ? (
<ActionableMessage
type="success"
className="home__new-network-notification"
autoHideTime={autoHideDelay}
onAutoHide={onAutoHide}
message={
<Box display={Display.InlineFlex}>
<i className="fa fa-check-circle home__new-nft-notification-icon" />
<Text variant={TextVariant.bodySm} as="h6">
{t('newNftAddedMessage')}
</Text>
<ButtonIcon
iconName={IconName.Close}
size={ButtonIconSize.Sm}
ariaLabel={t('close')}
onClick={onAutoHide}
/>
</Box>
}
/>
) : null}
{removeNftMessage === 'success' ? (
<ActionableMessage
type="danger"
className="home__new-network-notification"
autoHideTime={autoHideDelay}
onAutoHide={onAutoHide}
message={
<Box display={Display.InlineFlex}>
<i className="fa fa-check-circle home__new-nft-notification-icon" />
<Text variant={TextVariant.bodySm} as="h6">
{t('removeNftMessage')}
</Text>
<ButtonIcon
iconName={IconName.Close}
size={ButtonIconSize.Sm}
ariaLabel={t('close')}
onClick={onAutoHide}
/>
</Box>
}
/>
) : null}
{newNetworkAddedName ? (
<ActionableMessage
type="success"
className="home__new-network-notification"
message={
<Box display={Display.InlineFlex}>
<i className="fa fa-check-circle home__new-network-notification-icon" />
<Text variant={TextVariant.bodySm} as="h6">
{t('newNetworkAdded', [newNetworkAddedName])}
</Text>
<ButtonIcon
iconName={IconName.Close}
size={ButtonIconSize.Sm}
ariaLabel={t('close')}
onClick={() => clearNewNetworkAdded()}
className="home__new-network-notification-close"
/>
</Box>
}
/>
) : null}
{newTokensImported ? (
<ActionableMessage
type="success"
className="home__new-tokens-imported-notification"
message={
<Box display={Display.InlineFlex}>
<i className="fa fa-check-circle home__new-tokens-imported-notification-icon" />
<Box>
<Text
className="home__new-tokens-imported-notification-title"
variant={TextVariant.bodySmBold}
as="h6"
>
{t('newTokensImportedTitle')}
</Text>
<Text
className="home__new-tokens-imported-notification-message"
variant={TextVariant.bodySm}
as="h6"
>
{t('newTokensImportedMessage', [newTokensImported])}
</Text>
</Box>
<ButtonIcon
iconName={IconName.Close}
size={ButtonIconSize.Sm}
ariaLabel={t('close')}
onClick={() => setNewTokensImported('')}
className="home__new-tokens-imported-notification-close"
/>
</Box>
}
/>
) : null}
{shouldShowWeb3ShimUsageNotification ? (
<HomeNotification
descriptionText={t('web3ShimUsageNotification', [
<span
key="web3ShimUsageNotificationLink"
className="home-notification__text-link"
onClick={() =>
global.platform.openTab({ url: ZENDESK_URLS.LEGACY_WEB3 })
}
>
{t('here')}
</span>,
])}
ignoreText={t('dismiss')}
onIgnore={(disable) => {
setWeb3ShimUsageAlertDismissed(originOfCurrentTab);
if (disable) {
disableWeb3ShimUsageAlert();
}
}}
checkboxText={t('dontShowThisAgain')}
checkboxTooltipText={t('canToggleInSettings')}
key="home-web3ShimUsageNotification"
/>
) : null}
{
///: BEGIN:ONLY_INCLUDE_IN(build-main,build-beta,build-flask)
shouldShowSeedPhraseReminder ? (
<HomeNotification
descriptionText={t('backupApprovalNotice')}
acceptText={t('backupNow')}
onAccept={() => {
const backUpSRPRoute = `${ONBOARDING_SECURE_YOUR_WALLET_ROUTE}/?isFromReminder=true`;
if (isPopup) {
global.platform.openExtensionInBrowser(backUpSRPRoute);
} else {
history.push(backUpSRPRoute);
}
}}
infoText={t('backupApprovalInfo')}
key="home-backupApprovalNotice"
/>
) : null
///: END:ONLY_INCLUDE_IN
}
{infuraBlocked && this.state.canShowBlockageNotification ? (
<HomeNotification
descriptionText={t('infuraBlockedNotification', [
<span
key="infuraBlockedNotificationLink"
className="home-notification__text-link"
onClick={() =>
global.platform.openTab({ url: ZENDESK_URLS.INFURA_BLOCKAGE })
}
>
{t('here')}
</span>,
])}
ignoreText={t('dismiss')}
onIgnore={() => {
this.setState({
canShowBlockageNotification: false,
});
}}
key="home-infuraBlockedNotification"
/>
) : null}
{showOutdatedBrowserWarning ? (
<HomeNotification
descriptionText={t('outdatedBrowserNotification')}
acceptText={t('gotIt')}
onAccept={this.onOutdatedBrowserWarningClose}
key="home-outdatedBrowserNotification"
/>
) : null}
{newNetworkAddedConfigurationId && (
<Popover
className="home__new-network-added"
onClose={() => clearNewNetworkAdded()}
>
<i className="fa fa-check-circle fa-2x home__new-network-added__check-circle" />
<Text
variant={TextVariant.headingSm}
as="h4"
marginTop={5}
marginRight={9}
marginLeft={9}
marginBottom={0}
fontWeight={FontWeight.Bold}
>
{t('networkAddedSuccessfully')}
</Text>
<Box marginTop={8} marginRight={8} marginLeft={8} marginBottom={5}>
<Button
type="primary"
className="home__new-network-added__switch-to-button"
onClick={() => {
setActiveNetwork(newNetworkAddedConfigurationId);
clearNewNetworkAdded();
}}
>
<Text
variant={TextVariant.bodySm}
as="h6"
color={TextColor.primaryInverse}
>
{t('switchToNetwork', [newNetworkAddedName])}
</Text>
</Button>
<Button type="secondary" onClick={() => clearNewNetworkAdded()}>
<Text
variant={TextVariant.bodySm}
as="h6"
color={TextColor.primaryDefault}
>
{t('dismiss')}
</Text>
</Button>
</Box>
</Popover>
)}
</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={
<>
<a
href={ZENDESK_URLS.USER_GUIDE_DAPPS}
target="_blank"
rel="noopener noreferrer"
>
{t('learnMoreUpperCase')}
</a>
<Button
type="primary"
onClick={setConnectedStatusPopoverHasBeenShown}
>
{t('dismiss')}
</Button>
</>
}
>
<main className="home__connect-status-text">
<div>{t('metaMaskConnectStatusParagraphOne')}</div>
<div>{t('metaMaskConnectStatusParagraphTwo')}</div>
<div>{t('metaMaskConnectStatusParagraphThree')}</div>
</main>
</Popover>
);
};
render() {
const { t } = this.context;
const {
defaultHomeActiveTabName,
onTabClick,
forgottenPassword,
history,
///: BEGIN:ONLY_INCLUDE_IN(build-main,build-beta,build-flask)
connectedStatusPopoverHasBeenShown,
isPopup,
seedPhraseBackedUp,
showRecoveryPhraseReminder,
showTermsOfUsePopup,
///: END:ONLY_INCLUDE_IN
announcementsToShow,
showWhatsNewPopup,
hideWhatsNewPopup,
firstTimeFlowType,
completedOnboarding,
onboardedInThisUISession,
newNetworkAddedConfigurationId,
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
mmiPortfolioEnabled,
mmiPortfolioUrl,
///: END:ONLY_INCLUDE_IN
} = this.props;
if (forgottenPassword) {
return <Redirect to={{ pathname: RESTORE_VAULT_ROUTE }} />;
} else if (this.state.notificationClosing || this.state.redirecting) {
return null;
}
const tabPadding = process.env.MULTICHAIN ? 4 : 0; // TODO: Remove tabPadding and add paddingTop={4} to parent container Box of Tabs
const showWhatsNew =
completedOnboarding &&
(!onboardedInThisUISession || firstTimeFlowType === 'import') &&
announcementsToShow &&
showWhatsNewPopup &&
!process.env.IN_TEST &&
!newNetworkAddedConfigurationId;
///: BEGIN:ONLY_INCLUDE_IN(build-main,build-beta,build-flask)
const showTermsOfUse =
completedOnboarding && !onboardedInThisUISession && showTermsOfUsePopup;
///: END:ONLY_INCLUDE_IN
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
// The style in activity screen for support is different
const activitySupportDisplayStyle =
defaultHomeActiveTabName === 'activity'
? {
justifyContent: JustifyContent.center,
paddingLeft: 0,
marginTop: 4,
marginBottom: 4,
}
: {
justifyContent: JustifyContent.flexStart,
paddingLeft: 4,
marginTop: 0,
marginBottom: 4,
};
///: END:ONLY_INCLUDE_IN
return (
<div className="main-container">
<Route path={CONNECTED_ROUTE} component={ConnectedSites} exact />
<Route
path={CONNECTED_ACCOUNTS_ROUTE}
component={ConnectedAccounts}
exact
/>
<div className="home__container">
{showWhatsNew ? (
<WhatsNewPopup
onClose={hideWhatsNewPopup}
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
mmiPortfolioUrl={mmiPortfolioUrl}
///: END:ONLY_INCLUDE_IN
/>
) : null}
{
///: BEGIN:ONLY_INCLUDE_IN(build-main,build-beta,build-flask)
}
{!showWhatsNew && showRecoveryPhraseReminder ? (
<RecoveryPhraseReminder
hasBackedUp={seedPhraseBackedUp}
onConfirm={this.onRecoveryPhraseReminderClose}
/>
) : null}
{showTermsOfUse ? (
<TermsOfUsePopup onAccept={this.onAcceptTermsOfUse} />
) : null}
{isPopup && !connectedStatusPopoverHasBeenShown
? this.renderPopover()
: null}
{
///: END:ONLY_INCLUDE_IN
}
<div className="home__main-view">
{process.env.MULTICHAIN ? null : (
<div className="home__balance-wrapper">
{
///: BEGIN:ONLY_INCLUDE_IN(build-main,build-beta,build-flask)
<EthOverview showAddress />
///: END:ONLY_INCLUDE_IN
}
{
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
<EthOverview
showAddress
mmiPortfolioEnabled={mmiPortfolioEnabled}
mmiPortfolioUrl={mmiPortfolioUrl}
/>
///: END:ONLY_INCLUDE_IN
}
</div>
)}
<Box style={{ flexGrow: '1' }} paddingTop={tabPadding}>
<Tabs
t={this.context.t}
defaultActiveTabKey={defaultHomeActiveTabName}
onTabClick={(tabName) => {
onTabClick(tabName);
let event;
switch (tabName) {
case 'nfts':
event = MetaMetricsEventName.NftScreenOpened;
break;
case 'activity':
event = MetaMetricsEventName.ActivityScreenOpened;
break;
default:
event = MetaMetricsEventName.TokenScreenOpened;
}
this.context.trackEvent({
category: MetaMetricsEventCategory.Home,
event,
});
}}
tabsClassName="home__tabs"
>
<Tab
activeClassName="home__tab--active"
className="home__tab"
data-testid="home__asset-tab"
name={this.context.t('tokens')}
tabKey="tokens"
>
<Box marginTop={2}>
<AssetList
onClickAsset={(asset) =>
history.push(`${ASSET_ROUTE}/${asset}`)
}
/>
{
///: BEGIN:ONLY_INCLUDE_IN(build-main)
<ButtonLink
size={Size.MD}
startIconName={IconName.MessageQuestion}
data-testid="need-help-link"
href={SUPPORT_LINK}
display={Display.Flex}
justifyContent={JustifyContent.flexStart}
paddingLeft={4}
marginBottom={4}
onClick={this.onSupportLinkClick}
externalLink
>
{t('needHelpLinkText')}
</ButtonLink>
///: END:ONLY_INCLUDE_IN
}
</Box>
</Tab>
<Tab
activeClassName="home__tab--active"
className="home__tab"
data-testid="home__nfts-tab"
name={this.context.t('nfts')}
tabKey="nfts"
>
{
///: BEGIN:ONLY_INCLUDE_IN(build-main,build-beta,build-flask)
<NftsTab />
///: END:ONLY_INCLUDE_IN
}
{
///: BEGIN:ONLY_INCLUDE_IN(build-main)
<ButtonLink
size={Size.MD}
startIconName={IconName.MessageQuestion}
data-testid="need-help-link"
href={SUPPORT_LINK}
display={Display.Flex}
justifyContent={JustifyContent.flexStart}
paddingLeft={4}
marginBottom={4}
onClick={this.onSupportLinkClick}
externalLink
>
{t('needHelpLinkText')}
</ButtonLink>
///: END:ONLY_INCLUDE_IN
}
</Tab>
<Tab
activeClassName="home__tab--active"
className="home__tab"
data-testid="home__activity-tab"
name={t('activity')}
tabKey="activity"
>
<TransactionList />
{
///: BEGIN:ONLY_INCLUDE_IN(build-main)
<ButtonLink
size={Size.MD}
startIconName={IconName.MessageQuestion}
data-testid="need-help-link"
href={SUPPORT_LINK}
display={Display.Flex}
justifyContent={JustifyContent.center}
marginBottom={4}
marginTop={4}
onClick={this.onSupportLinkClick}
externalLink
>
{t('needHelpLinkText')}
</ButtonLink>
///: END:ONLY_INCLUDE_IN
}
</Tab>
</Tabs>
{
///: BEGIN:ONLY_INCLUDE_IN(build-mmi)
<InstitutionalHomeFooter
activitySupportDisplayStyle={activitySupportDisplayStyle}
/>
///: END:ONLY_INCLUDE_IN
}
</Box>
{
///: BEGIN:ONLY_INCLUDE_IN(build-beta)
<div className="home__support">
<BetaHomeFooter />
</div>
///: END:ONLY_INCLUDE_IN
}
{
///: BEGIN:ONLY_INCLUDE_IN(build-flask)
<div className="home__support">
<FlaskHomeFooter />
</div>
///: END:ONLY_INCLUDE_IN
}
</div>
{this.renderNotifications()}
</div>
</div>
);
}
}