Add entry point for metalabs dapp into metamask home page (#15407)

Co-authored-by: Dan Miller <danjm.com@gmail.com>
feature/default_network_editable
Matthew Epps 2 years ago committed by GitHub
parent 0b1744d4eb
commit dcfe80c255
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      .metamaskrc.dist
  2. 15
      app/_locales/en/messages.json
  3. 10
      app/scripts/controllers/app-state.js
  4. 2
      app/scripts/metamask-controller.js
  5. 1
      development/build/scripts.js
  6. 1
      shared/constants/metametrics.js
  7. 3
      test/e2e/fixtures/address-entry/state.json
  8. 3
      test/e2e/fixtures/connected-state/state.json
  9. 3
      test/e2e/fixtures/custom-rpc/state.json
  10. 3
      test/e2e/fixtures/custom-token/state.json
  11. 3
      test/e2e/fixtures/eip-1559-v2-dapp/state.json
  12. 3
      test/e2e/fixtures/eip-1559-v2/state.json
  13. 3
      test/e2e/fixtures/import-ui/state.json
  14. 3
      test/e2e/fixtures/imported-account/state.json
  15. 3
      test/e2e/fixtures/localization/state.json
  16. 3
      test/e2e/fixtures/metrics-enabled/state.json
  17. 3
      test/e2e/fixtures/navigate-transactions/state.json
  18. 3
      test/e2e/fixtures/send-edit-v2/state.json
  19. 3
      test/e2e/fixtures/send-edit/state.json
  20. 3
      test/e2e/fixtures/special-settings/state.json
  21. 3
      test/e2e/fixtures/threebox-enabled/state.json
  22. 45
      ui/components/ui/icon/icon-chart.js
  23. 5
      ui/components/ui/tabs/tabs.component.js
  24. 4
      ui/components/ui/tooltip/tooltip.js
  25. 17
      ui/ducks/app/app.js
  26. 82
      ui/pages/home/home.component.js
  27. 10
      ui/pages/home/home.container.js
  28. 52
      ui/pages/home/index.scss
  29. 4
      ui/selectors/selectors.js
  30. 3
      ui/store/actionConstants.js
  31. 4
      ui/store/actions.js

@ -8,6 +8,7 @@ COLLECTIBLES_V1=
PUBNUB_PUB_KEY= PUBNUB_PUB_KEY=
PUBNUB_SUB_KEY= PUBNUB_SUB_KEY=
TOKEN_ALLOWANCE_IMPROVEMENTS= TOKEN_ALLOWANCE_IMPROVEMENTS=
PORTFOLIO_URL=
; Set this to '1' to enable support for Sign-In with Ethereum [EIP-4361](https://eips.ethereum.org/EIPS/eip-4361) ; Set this to '1' to enable support for Sign-In with Ethereum [EIP-4361](https://eips.ethereum.org/EIPS/eip-4361)
SIWE_V1= SIWE_V1=

@ -451,6 +451,9 @@
"betaMetamaskVersion": { "betaMetamaskVersion": {
"message": "MetaMask Beta Version" "message": "MetaMask Beta Version"
}, },
"betaPortfolioSite": {
"message": "beta portfolio site"
},
"betaWelcome": { "betaWelcome": {
"message": "Welcome to MetaMask Beta" "message": "Welcome to MetaMask Beta"
}, },
@ -1779,6 +1782,9 @@
"message": "JSON File", "message": "JSON File",
"description": "format for importing an account" "description": "format for importing an account"
}, },
"keepTapsOnTokens": {
"message": "to keep tabs on your tokens and NFTs across accounts and networks."
},
"keystone": { "keystone": {
"message": "Keystone" "message": "Keystone"
}, },
@ -2165,6 +2171,9 @@
"nevermind": { "nevermind": {
"message": "Nevermind" "message": "Nevermind"
}, },
"new": {
"message": "New!"
},
"newAccount": { "newAccount": {
"message": "New account" "message": "New account"
}, },
@ -2660,6 +2669,9 @@
"popularCustomNetworks": { "popularCustomNetworks": {
"message": "Popular custom networks" "message": "Popular custom networks"
}, },
"portfolioSite": {
"message": "Portfolio site"
},
"preferredLedgerConnectionType": { "preferredLedgerConnectionType": {
"message": "Preferred Ledger connection type", "message": "Preferred Ledger connection type",
"description": "A header for a dropdown in Settings > Advanced. Appears above the ledgerConnectionPreferenceDescription message" "description": "A header for a dropdown in Settings > Advanced. Appears above the ledgerConnectionPreferenceDescription message"
@ -4075,6 +4087,9 @@
"tryAgain": { "tryAgain": {
"message": "Try again" "message": "Try again"
}, },
"tryOur": {
"message": "Try our"
},
"turnOnTokenDetection": { "turnOnTokenDetection": {
"message": "Turn on enhanced token detection" "message": "Turn on enhanced token detection"
}, },

@ -33,6 +33,7 @@ export default class AppStateController extends EventEmitter {
collectiblesDetectionNoticeDismissed: false, collectiblesDetectionNoticeDismissed: false,
enableEIP1559V2NoticeDismissed: false, enableEIP1559V2NoticeDismissed: false,
showTestnetMessageInDropdown: true, showTestnetMessageInDropdown: true,
showPortfolioTooltip: true,
trezorModel: null, trezorModel: null,
...initState, ...initState,
qrHardware: {}, qrHardware: {},
@ -259,6 +260,15 @@ export default class AppStateController extends EventEmitter {
this.store.updateState({ showTestnetMessageInDropdown }); this.store.updateState({ showTestnetMessageInDropdown });
} }
/**
* Sets whether the portfolio site tooltip should be shown on the home page
*
* @param showPortfolioTooltip
*/
setShowPortfolioTooltip(showPortfolioTooltip) {
this.store.updateState({ showPortfolioTooltip });
}
/** /**
* Sets a property indicating the model of the user's Trezor hardware wallet * Sets a property indicating the model of the user's Trezor hardware wallet
* *

@ -1727,6 +1727,8 @@ export default class MetamaskController extends EventEmitter {
appStateController.setShowTestnetMessageInDropdown.bind( appStateController.setShowTestnetMessageInDropdown.bind(
appStateController, appStateController,
), ),
setShowPortfolioTooltip:
appStateController.setShowPortfolioTooltip.bind(appStateController),
setCollectiblesDetectionNoticeDismissed: setCollectiblesDetectionNoticeDismissed:
appStateController.setCollectiblesDetectionNoticeDismissed.bind( appStateController.setCollectiblesDetectionNoticeDismissed.bind(
appStateController, appStateController,

@ -1023,6 +1023,7 @@ async function getEnvironmentVariables({ buildTarget, buildType, version }) {
environment, environment,
testing, testing,
}), }),
PORTFOLIO_URL: ENVIRONMENT.PORTFOLIO_URL || 'https://portfolio.metamask.io',
METAMASK_DEBUG: devMode, METAMASK_DEBUG: devMode,
METAMASK_ENVIRONMENT: environment, METAMASK_ENVIRONMENT: environment,
METAMASK_VERSION: version, METAMASK_VERSION: version,

@ -323,6 +323,7 @@ export const EVENT_NAMES = {
PERMISSIONS_APPROVED: 'Permissions Approved', PERMISSIONS_APPROVED: 'Permissions Approved',
PERMISSIONS_REJECTED: 'Permissions Rejected', PERMISSIONS_REJECTED: 'Permissions Rejected',
PERMISSIONS_REQUESTED: 'Permissions Requested', PERMISSIONS_REQUESTED: 'Permissions Requested',
PORTFOLIO_LINK_CLICKED: 'Portfolio Link Clicked',
PUBLIC_ADDRESS_COPIED: 'Public Address Copied', PUBLIC_ADDRESS_COPIED: 'Public Address Copied',
PROVIDER_METHOD_CALLED: 'Provider Method Called', PROVIDER_METHOD_CALLED: 'Provider Method Called',
SIGNATURE_APPROVED: 'Signature Approved', SIGNATURE_APPROVED: 'Signature Approved',

@ -15,7 +15,8 @@
}, },
"AppStateController": { "AppStateController": {
"mkrMigrationReminderTimestamp": null, "mkrMigrationReminderTimestamp": null,
"swapsWelcomeMessageHasBeenShown": true "swapsWelcomeMessageHasBeenShown": true,
"showPortfolioTooltip": false
}, },
"CachedBalancesController": { "CachedBalancesController": {
"cachedBalances": { "cachedBalances": {

@ -1,7 +1,8 @@
{ {
"data": { "data": {
"AppStateController": { "AppStateController": {
"connectedStatusPopoverHasBeenShown": false "connectedStatusPopoverHasBeenShown": false,
"showPortfolioTooltip": false
}, },
"CachedBalancesController": { "CachedBalancesController": {
"cachedBalances": { "cachedBalances": {

@ -1,7 +1,8 @@
{ {
"data": { "data": {
"AppStateController": { "AppStateController": {
"mkrMigrationReminderTimestamp": null "mkrMigrationReminderTimestamp": null,
"showPortfolioTooltip": false
}, },
"CachedBalancesController": { "CachedBalancesController": {
"cachedBalances": { "cachedBalances": {

@ -12,7 +12,8 @@
"connectedStatusPopoverHasBeenShown": true, "connectedStatusPopoverHasBeenShown": true,
"defaultHomeActiveTabName": null, "defaultHomeActiveTabName": null,
"recoveryPhraseReminderHasBeenShown": true, "recoveryPhraseReminderHasBeenShown": true,
"recoveryPhraseReminderLastShown": "__FIXTURE_SUBSTITUTION__currentDateInMilliseconds" "recoveryPhraseReminderLastShown": "__FIXTURE_SUBSTITUTION__currentDateInMilliseconds",
"showPortfolioTooltip": false
}, },
"CachedBalancesController": { "CachedBalancesController": {
"cachedBalances": { "cachedBalances": {

@ -2,7 +2,8 @@
"data": { "data": {
"AppStateController": { "AppStateController": {
"mkrMigrationReminderTimestamp": null, "mkrMigrationReminderTimestamp": null,
"swapsWelcomeMessageHasBeenShown": true "swapsWelcomeMessageHasBeenShown": true,
"showPortfolioTooltip": false
}, },
"CachedBalancesController": { "CachedBalancesController": {
"cachedBalances": { "cachedBalances": {

@ -2,7 +2,8 @@
"data": { "data": {
"AppStateController": { "AppStateController": {
"mkrMigrationReminderTimestamp": null, "mkrMigrationReminderTimestamp": null,
"swapsWelcomeMessageHasBeenShown": true "swapsWelcomeMessageHasBeenShown": true,
"showPortfolioTooltip": false
}, },
"CachedBalancesController": { "CachedBalancesController": {
"cachedBalances": { "cachedBalances": {

@ -259,7 +259,8 @@
"AppStateController": { "AppStateController": {
"connectedStatusPopoverHasBeenShown": true, "connectedStatusPopoverHasBeenShown": true,
"swapsWelcomeMessageHasBeenShown": false, "swapsWelcomeMessageHasBeenShown": false,
"defaultHomeActiveTabName": "Activity" "defaultHomeActiveTabName": "Activity",
"showPortfolioTooltip": false
} }
}, },
"meta": { "meta": {

@ -1,7 +1,8 @@
{ {
"data": { "data": {
"AppStateController": { "AppStateController": {
"mkrMigrationReminderTimestamp": null "mkrMigrationReminderTimestamp": null,
"showPortfolioTooltip": false
}, },
"CachedBalancesController": { "CachedBalancesController": {
"cachedBalances": { "cachedBalances": {

@ -1,7 +1,8 @@
{ {
"data": { "data": {
"AppStateController": { "AppStateController": {
"mkrMigrationReminderTimestamp": null "mkrMigrationReminderTimestamp": null,
"showPortfolioTooltip": false
}, },
"CachedBalancesController": { "CachedBalancesController": {
"cachedBalances": { "cachedBalances": {

@ -1,7 +1,8 @@
{ {
"data": { "data": {
"AppStateController": { "AppStateController": {
"connectedStatusPopoverHasBeenShown": false "connectedStatusPopoverHasBeenShown": false,
"showPortfolioTooltip": false
}, },
"CachedBalancesController": { "CachedBalancesController": {
"cachedBalances": { "cachedBalances": {

@ -1,7 +1,8 @@
{ {
"data": { "data": {
"AppStateController": { "AppStateController": {
"mkrMigrationReminderTimestamp": null "mkrMigrationReminderTimestamp": null,
"showPortfolioTooltip": false
}, },
"CachedBalancesController": { "CachedBalancesController": {
"cachedBalances": { "cachedBalances": {

@ -2,7 +2,8 @@
"data": { "data": {
"AppStateController": { "AppStateController": {
"mkrMigrationReminderTimestamp": null, "mkrMigrationReminderTimestamp": null,
"swapsWelcomeMessageHasBeenShown": true "swapsWelcomeMessageHasBeenShown": true,
"showPortfolioTooltip": false
}, },
"CachedBalancesController": { "CachedBalancesController": {
"cachedBalances": { "cachedBalances": {

@ -2,7 +2,8 @@
"data": { "data": {
"AppStateController": { "AppStateController": {
"mkrMigrationReminderTimestamp": null, "mkrMigrationReminderTimestamp": null,
"swapsWelcomeMessageHasBeenShown": true "swapsWelcomeMessageHasBeenShown": true,
"showPortfolioTooltip": false
}, },
"CachedBalancesController": { "CachedBalancesController": {
"cachedBalances": { "cachedBalances": {

@ -1,7 +1,8 @@
{ {
"data": { "data": {
"AppStateController": { "AppStateController": {
"mkrMigrationReminderTimestamp": null "mkrMigrationReminderTimestamp": null,
"showPortfolioTooltip": false
}, },
"CachedBalancesController": { "CachedBalancesController": {
"cachedBalances": { "cachedBalances": {

@ -2,7 +2,8 @@
"data": { "data": {
"AppStateController": { "AppStateController": {
"swapsWelcomeMessageHasBeenShown": true, "swapsWelcomeMessageHasBeenShown": true,
"connectedStatusPopoverHasBeenShown": false "connectedStatusPopoverHasBeenShown": false,
"showPortfolioTooltip": false
}, },
"CachedBalancesController": { "CachedBalancesController": {
"cachedBalances": { "cachedBalances": {

@ -0,0 +1,45 @@
import React from 'react';
import PropTypes from 'prop-types';
const IconChart = ({
size = 12,
color = 'var(--color-primary-default)',
className,
ariaLabel,
}) => (
<svg
width={size}
height={size}
viewBox="0 0 12 12"
fill="none"
className={className}
aria-label={ariaLabel}
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M1.5 9.375C1.5 9.58125 1.66781 9.75 1.875 9.75H11.25C11.6648 9.75 12 10.0852 12 10.5C12 10.9148 11.6648 11.25 11.25 11.25H1.875C0.839531 11.25 0 10.4109 0 9.375V1.5C0 1.08586 0.335859 0.75 0.75 0.75C1.16414 0.75 1.5 1.08586 1.5 1.5V9.375ZM8.02969 6.52969C7.73672 6.82266 7.26328 6.82266 6.97031 6.52969L5.625 5.18672L3.52969 7.27969C3.23672 7.57266 2.76328 7.57266 2.47031 7.27969C2.17688 6.98672 2.17688 6.51328 2.47031 6.22031L5.09531 3.59531C5.38828 3.30234 5.86172 3.30234 6.15469 3.59531L7.5 4.93828L9.97031 2.47031C10.2633 2.17687 10.7367 2.17687 11.0297 2.47031C11.3227 2.76328 11.3227 3.23672 11.0297 3.52969L8.02969 6.52969Z"
fill={color}
/>
</svg>
);
IconChart.propTypes = {
/**
* The size of the Icon follows an 8px grid 2 = 16px, 3 = 24px etc
*/
size: PropTypes.number,
/**
* The color of the icon accepts design token css variables
*/
color: PropTypes.string,
/**
* An additional className to assign the Icon
*/
className: PropTypes.string,
/**
* The aria-label of the icon for accessibility purposes
*/
ariaLabel: PropTypes.string,
};
export default IconChart;

@ -7,6 +7,7 @@ export default class Tabs extends Component {
defaultActiveTabName: null, defaultActiveTabName: null,
onTabClick: null, onTabClick: null,
tabsClassName: undefined, tabsClassName: undefined,
subHeader: null,
}; };
static propTypes = { static propTypes = {
@ -14,6 +15,7 @@ export default class Tabs extends Component {
onTabClick: PropTypes.func, onTabClick: PropTypes.func,
children: PropTypes.node.isRequired, children: PropTypes.node.isRequired,
tabsClassName: PropTypes.string, tabsClassName: PropTypes.string,
subHeader: PropTypes.node,
}; };
state = { state = {
@ -74,12 +76,13 @@ export default class Tabs extends Component {
} }
render() { render() {
const { tabsClassName } = this.props; const { tabsClassName, subHeader } = this.props;
return ( return (
<div className="tabs"> <div className="tabs">
<ul className={classnames('tabs__list', tabsClassName)}> <ul className={classnames('tabs__list', tabsClassName)}>
{this.renderTabs()} {this.renderTabs()}
</ul> </ul>
{subHeader}
<div className="tabs__content">{this.renderActiveTabContent()}</div> <div className="tabs__content">{this.renderActiveTabContent()}</div>
</div> </div>
); );

@ -12,6 +12,7 @@ export default class Tooltip extends PureComponent {
onHidden: null, onHidden: null,
position: 'left', position: 'left',
offset: 0, offset: 0,
open: undefined,
size: 'small', size: 'small',
title: null, title: null,
trigger: 'mouseenter focus', trigger: 'mouseenter focus',
@ -29,6 +30,7 @@ export default class Tooltip extends PureComponent {
interactive: PropTypes.bool, interactive: PropTypes.bool,
offset: PropTypes.number, offset: PropTypes.number,
onHidden: PropTypes.func, onHidden: PropTypes.func,
open: PropTypes.bool,
position: PropTypes.oneOf(['top', 'right', 'bottom', 'left']), position: PropTypes.oneOf(['top', 'right', 'bottom', 'left']),
size: PropTypes.oneOf(['small', 'regular', 'big']), size: PropTypes.oneOf(['small', 'regular', 'big']),
title: PropTypes.string, title: PropTypes.string,
@ -54,6 +56,7 @@ export default class Tooltip extends PureComponent {
trigger, trigger,
onHidden, onHidden,
offset, offset,
open,
wrapperClassName, wrapperClassName,
style, style,
theme, theme,
@ -82,6 +85,7 @@ export default class Tooltip extends PureComponent {
style={style} style={style}
title={disabled ? '' : title} title={disabled ? '' : title}
trigger={trigger} trigger={trigger}
open={open}
theme={`tippy-tooltip--mm-custom ${theme}`} // Required for correct theming theme={`tippy-tooltip--mm-custom ${theme}`} // Required for correct theming
tabIndex={tabIndex || 0} tabIndex={tabIndex || 0}
tag={tag} tag={tag}

@ -58,6 +58,7 @@ export default function reduceApp(state = {}, action) {
ledgerTransportStatus: TRANSPORT_STATES.NONE, ledgerTransportStatus: TRANSPORT_STATES.NONE,
newNetworkAdded: '', newNetworkAdded: '',
newCollectibleAddedMessage: '', newCollectibleAddedMessage: '',
portfolioTooltipWasShownInThisSession: false,
sendInputCurrencySwitched: false, sendInputCurrencySwitched: false,
newTokensImported: '', newTokensImported: '',
newCustomNetworkAdded: {}, newCustomNetworkAdded: {},
@ -321,6 +322,12 @@ export default function reduceApp(state = {}, action) {
newCollectibleAddedMessage: action.value, newCollectibleAddedMessage: action.value,
}; };
case actionConstants.PORTFOLIO_TOOLTIP_WAS_SHOWN_IN_THIS_SESSION:
return {
...appState,
portfolioTooltipWasShownInThisSession: true,
};
case actionConstants.LOADING_METHOD_DATA_STARTED: case actionConstants.LOADING_METHOD_DATA_STARTED:
return { return {
...appState, ...appState,
@ -418,6 +425,12 @@ export function hideWhatsNewPopup() {
}; };
} }
export function setPortfolioTooltipWasShownInThisSession() {
return {
type: actionConstants.PORTFOLIO_TOOLTIP_WAS_SHOWN_IN_THIS_SESSION,
};
}
export function toggleGasLoadingAnimation(value) { export function toggleGasLoadingAnimation(value) {
return { type: actionConstants.TOGGLE_GAS_LOADING_ANIMATION, value }; return { type: actionConstants.TOGGLE_GAS_LOADING_ANIMATION, value };
} }
@ -447,6 +460,10 @@ export function getLedgerTransportStatus(state) {
return state.appState.ledgerTransportStatus; return state.appState.ledgerTransportStatus;
} }
export function getPortfolioTooltipWasShownInThisSession(state) {
return state.appState.portfolioTooltipWasShownInThisSession;
}
export function toggleCurrencySwitch() { export function toggleCurrencySwitch() {
return { type: actionConstants.TOGGLE_CURRENCY_INPUT_SWITCH }; return { type: actionConstants.TOGGLE_CURRENCY_INPUT_SWITCH };
} }

@ -3,12 +3,12 @@ import PropTypes from 'prop-types';
import { Redirect, Route } from 'react-router-dom'; import { Redirect, Route } from 'react-router-dom';
///: BEGIN:ONLY_INCLUDE_IN(main) ///: BEGIN:ONLY_INCLUDE_IN(main)
import { SUPPORT_LINK } from '../../helpers/constants/common'; import { SUPPORT_LINK } from '../../helpers/constants/common';
///: END:ONLY_INCLUDE_IN
import { import {
EVENT, EVENT,
EVENT_NAMES, EVENT_NAMES,
CONTEXT_PROPS, CONTEXT_PROPS,
} from '../../../shared/constants/metametrics'; } from '../../../shared/constants/metametrics';
///: END:ONLY_INCLUDE_IN
import { formatDate } from '../../helpers/utils/util'; import { formatDate } from '../../helpers/utils/util';
import AssetList from '../../components/app/asset-list'; import AssetList from '../../components/app/asset-list';
import CollectiblesTab from '../../components/app/collectibles-tab'; import CollectiblesTab from '../../components/app/collectibles-tab';
@ -27,6 +27,7 @@ import WhatsNewPopup from '../../components/app/whats-new-popup';
import RecoveryPhraseReminder from '../../components/app/recovery-phrase-reminder'; import RecoveryPhraseReminder from '../../components/app/recovery-phrase-reminder';
import ActionableMessage from '../../components/ui/actionable-message/actionable-message'; import ActionableMessage from '../../components/ui/actionable-message/actionable-message';
import Typography from '../../components/ui/typography/typography'; import Typography from '../../components/ui/typography/typography';
import IconChart from '../../components/ui/icon/icon-chart';
import { import {
TYPOGRAPHY, TYPOGRAPHY,
FONT_WEIGHT, FONT_WEIGHT,
@ -50,6 +51,7 @@ import {
ADD_COLLECTIBLE_ROUTE, ADD_COLLECTIBLE_ROUTE,
} from '../../helpers/constants/routes'; } from '../../helpers/constants/routes';
import ZENDESK_URLS from '../../helpers/constants/zendesk-url'; import ZENDESK_URLS from '../../helpers/constants/zendesk-url';
import Tooltip from '../../components/ui/tooltip';
///: BEGIN:ONLY_INCLUDE_IN(beta) ///: BEGIN:ONLY_INCLUDE_IN(beta)
import BetaHomeFooter from './beta/beta-home-footer.component'; import BetaHomeFooter from './beta/beta-home-footer.component';
///: END:ONLY_INCLUDE_IN ///: END:ONLY_INCLUDE_IN
@ -115,6 +117,10 @@ export default class Home extends PureComponent {
infuraBlocked: PropTypes.bool.isRequired, infuraBlocked: PropTypes.bool.isRequired,
showWhatsNewPopup: PropTypes.bool.isRequired, showWhatsNewPopup: PropTypes.bool.isRequired,
hideWhatsNewPopup: PropTypes.func.isRequired, hideWhatsNewPopup: PropTypes.func.isRequired,
showPortfolioTooltip: PropTypes.bool.isRequired,
hidePortfolioTooltip: PropTypes.func.isRequired,
portfolioTooltipWasShownInThisSession: PropTypes.bool.isRequired,
setPortfolioTooltipWasShownInThisSession: PropTypes.func.isRequired,
announcementsToShow: PropTypes.bool.isRequired, announcementsToShow: PropTypes.bool.isRequired,
///: BEGIN:ONLY_INCLUDE_IN(flask) ///: BEGIN:ONLY_INCLUDE_IN(flask)
errorsToShow: PropTypes.object.isRequired, errorsToShow: PropTypes.object.isRequired,
@ -213,7 +219,12 @@ export default class Home extends PureComponent {
} }
componentDidMount() { componentDidMount() {
const { setPortfolioTooltipWasShownInThisSession, showPortfolioTooltip } =
this.props;
this.checkStatusAndNavigate(); this.checkStatusAndNavigate();
if (showPortfolioTooltip) {
setPortfolioTooltipWasShownInThisSession();
}
} }
static getDerivedStateFromProps(props) { static getDerivedStateFromProps(props) {
@ -594,6 +605,9 @@ export default class Home extends PureComponent {
announcementsToShow, announcementsToShow,
showWhatsNewPopup, showWhatsNewPopup,
hideWhatsNewPopup, hideWhatsNewPopup,
showPortfolioTooltip,
hidePortfolioTooltip,
portfolioTooltipWasShownInThisSession,
seedPhraseBackedUp, seedPhraseBackedUp,
showRecoveryPhraseReminder, showRecoveryPhraseReminder,
firstTimeFlowType, firstTimeFlowType,
@ -610,8 +624,9 @@ export default class Home extends PureComponent {
((completedOnboarding && firstTimeFlowType === 'import') || ((completedOnboarding && firstTimeFlowType === 'import') ||
!completedOnboarding) && !completedOnboarding) &&
announcementsToShow && announcementsToShow &&
showWhatsNewPopup; showWhatsNewPopup &&
!showPortfolioTooltip &&
!portfolioTooltipWasShownInThisSession;
return ( return (
<div className="main-container"> <div className="main-container">
<Route path={CONNECTED_ROUTE} component={ConnectedSites} exact /> <Route path={CONNECTED_ROUTE} component={ConnectedSites} exact />
@ -640,6 +655,67 @@ export default class Home extends PureComponent {
defaultActiveTabName={defaultHomeActiveTabName} defaultActiveTabName={defaultHomeActiveTabName}
onTabClick={onTabClick} onTabClick={onTabClick}
tabsClassName="home__tabs" tabsClassName="home__tabs"
subHeader={
<Tooltip
position="bottom"
open={!process.env.IN_TEST && showPortfolioTooltip}
interactive
theme="home__subheader-link--tooltip"
html={
<div>
<div className="home__subheader-link--tooltip-content-header">
<div className="home__subheader-link--tooltip-content-header-text">
{t('new')}
</div>
<button
className="home__subheader-link--tooltip-content-header-button"
onClick={() => {
hidePortfolioTooltip();
}}
>
<i className="fa fa-times" />
</button>
</div>
<div>
{t('tryOur')}&nbsp;
<span className="home__subheader-link--tooltip-content-text-bold">
{t('betaPortfolioSite')}
</span>
&nbsp;{t('keepTapsOnTokens')}
</div>
</div>
}
>
<div
className="home__subheader-link"
onClick={async () => {
const portfolioUrl = process.env.PORTFOLIO_URL;
global.platform.openTab({
url: `${portfolioUrl}?metamaskEntry=ext`,
});
this.context.trackEvent(
{
category: EVENT.CATEGORIES.HOME,
event: EVENT_NAMES.PORTFOLIO_LINK_CLICKED,
properties: {
url: portfolioUrl,
},
},
{
contextPropsIntoEventProperties: [
CONTEXT_PROPS.PAGE_TITLE,
],
},
);
}}
>
<IconChart />
<div className="home__subheader-link--text">
{t('portfolioSite')}
</div>
</div>
</Tooltip>
}
> >
<Tab <Tab
activeClassName="home__tab--active" activeClassName="home__tab--active"

@ -23,6 +23,7 @@ import {
hasUnsignedQRHardwareMessage, hasUnsignedQRHardwareMessage,
getNewCollectibleAddedMessage, getNewCollectibleAddedMessage,
getNewTokensImported, getNewTokensImported,
getShowPortfolioTooltip,
} from '../../selectors'; } from '../../selectors';
import { import {
@ -30,6 +31,7 @@ import {
restoreFromThreeBox, restoreFromThreeBox,
turnThreeBoxSyncingOn, turnThreeBoxSyncingOn,
getThreeBoxLastUpdated, getThreeBoxLastUpdated,
hidePortfolioTooltip,
setShowRestorePromptToFalse, setShowRestorePromptToFalse,
setConnectedStatusPopoverHasBeenShown, setConnectedStatusPopoverHasBeenShown,
setDefaultHomeActiveTabName, setDefaultHomeActiveTabName,
@ -49,6 +51,8 @@ import {
setThreeBoxLastUpdated, setThreeBoxLastUpdated,
hideWhatsNewPopup, hideWhatsNewPopup,
setNewCustomNetworkAdded, setNewCustomNetworkAdded,
getPortfolioTooltipWasShownInThisSession,
setPortfolioTooltipWasShownInThisSession,
} from '../../ducks/app/app'; } from '../../ducks/app/app';
import { getWeb3ShimUsageAlertEnabledness } from '../../ducks/metamask/metamask'; import { getWeb3ShimUsageAlertEnabledness } from '../../ducks/metamask/metamask';
import { getSwapsFeatureIsLive } from '../../ducks/swaps/swaps'; import { getSwapsFeatureIsLive } from '../../ducks/swaps/swaps';
@ -149,6 +153,9 @@ const mapStateToProps = (state) => {
shouldShowErrors: Object.entries(metamask.snapErrors || []).length > 0, shouldShowErrors: Object.entries(metamask.snapErrors || []).length > 0,
///: END:ONLY_INCLUDE_IN ///: END:ONLY_INCLUDE_IN
showWhatsNewPopup: getShowWhatsNewPopup(state), showWhatsNewPopup: getShowWhatsNewPopup(state),
showPortfolioTooltip: getShowPortfolioTooltip(state),
portfolioTooltipWasShownInThisSession:
getPortfolioTooltipWasShownInThisSession(state),
showRecoveryPhraseReminder: getShowRecoveryPhraseReminder(state), showRecoveryPhraseReminder: getShowRecoveryPhraseReminder(state),
seedPhraseBackedUp, seedPhraseBackedUp,
newNetworkAdded: getNewNetworkAdded(state), newNetworkAdded: getNewNetworkAdded(state),
@ -185,6 +192,7 @@ const mapDispatchToProps = (dispatch) => ({
disableWeb3ShimUsageAlert: () => disableWeb3ShimUsageAlert: () =>
setAlertEnabledness(ALERT_TYPES.web3ShimUsage, false), setAlertEnabledness(ALERT_TYPES.web3ShimUsage, false),
hideWhatsNewPopup: () => dispatch(hideWhatsNewPopup()), hideWhatsNewPopup: () => dispatch(hideWhatsNewPopup()),
hidePortfolioTooltip,
setRecoveryPhraseReminderHasBeenShown: () => setRecoveryPhraseReminderHasBeenShown: () =>
dispatch(setRecoveryPhraseReminderHasBeenShown()), dispatch(setRecoveryPhraseReminderHasBeenShown()),
setRecoveryPhraseReminderLastShown: (lastShown) => setRecoveryPhraseReminderLastShown: (lastShown) =>
@ -204,6 +212,8 @@ const mapDispatchToProps = (dispatch) => ({
setRpcTarget: (rpcUrl, chainId, ticker, nickname) => { setRpcTarget: (rpcUrl, chainId, ticker, nickname) => {
dispatch(setRpcTarget(rpcUrl, chainId, ticker, nickname)); dispatch(setRpcTarget(rpcUrl, chainId, ticker, nickname));
}, },
setPortfolioTooltipWasShownInThisSession: () =>
dispatch(setPortfolioTooltipWasShownInThisSession()),
}); });
export default compose( export default compose(

@ -221,4 +221,56 @@
margin-bottom: 16px; margin-bottom: 16px;
} }
} }
&__subheader-link {
display: flex;
padding: 12px 0;
justify-content: center;
color: var(--color-primary-default);
align-items: center;
cursor: pointer;
&--tooltip-content {
&-header {
display: flex;
justify-content: space-between;
margin-bottom: 8px;
&-text {
font-size: 18px;
line-height: 22.82px;
font-weight: 700;
}
&-button {
background-color: var(--color-primary-default);
color: var(--color-primary-inverse);
border: 0;
}
}
&-text-bold {
font-weight: 700;
}
}
&--tooltip-theme {
background-color: var(--color-primary-default) !important;
& .tippy-tooltip-content {
color: var(--color-primary-inverse) !important;
}
& .arrow-regular {
border-bottom-color: var(--color-primary-default) !important;
}
}
&--text {
margin-left: 8px;
font-weight: 400;
font-size: 12px;
line-height: 140.62%;
}
}
} }

@ -878,6 +878,10 @@ export function getShowRecoveryPhraseReminder(state) {
return currentTime - recoveryPhraseReminderLastShown >= frequency; return currentTime - recoveryPhraseReminderLastShown >= frequency;
} }
export function getShowPortfolioTooltip(state) {
return state.metamask.showPortfolioTooltip;
}
/** /**
* To get the useTokenDetection flag which determines whether a static or dynamic token list is used * To get the useTokenDetection flag which determines whether a static or dynamic token list is used
* *

@ -106,7 +106,8 @@ export const SET_OPEN_METAMASK_TAB_IDS = 'SET_OPEN_METAMASK_TAB_IDS';
// Home Screen // Home Screen
export const HIDE_WHATS_NEW_POPUP = 'HIDE_WHATS_NEW_POPUP'; export const HIDE_WHATS_NEW_POPUP = 'HIDE_WHATS_NEW_POPUP';
export const PORTFOLIO_TOOLTIP_WAS_SHOWN_IN_THIS_SESSION =
'PORTFOLIO_TOOLTIP_WAS_SHOWN_IN_THIS_SESSION';
export const TOGGLE_GAS_LOADING_ANIMATION = 'TOGGLE_GAS_LOADING_ANIMATION'; export const TOGGLE_GAS_LOADING_ANIMATION = 'TOGGLE_GAS_LOADING_ANIMATION';
// Smart Transactions // Smart Transactions

@ -3854,6 +3854,10 @@ export function hideTestNetMessage() {
return submitRequestToBackground('setShowTestnetMessageInDropdown', [false]); return submitRequestToBackground('setShowTestnetMessageInDropdown', [false]);
} }
export function hidePortfolioTooltip() {
return submitRequestToBackground('setShowPortfolioTooltip', [false]);
}
export function setCollectiblesDetectionNoticeDismissed() { export function setCollectiblesDetectionNoticeDismissed() {
return submitRequestToBackground('setCollectiblesDetectionNoticeDismissed', [ return submitRequestToBackground('setCollectiblesDetectionNoticeDismissed', [
true, true,

Loading…
Cancel
Save