mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
New notification fixes (#6955)
* Replace use of backup-notification with use of home notification * Pin notifications relative to window * Remove unneeded isRequired condition on some home.component properties * Refactor rendering of home notifications * UX for multiple notifications * Adds dismissal to provider request notification. * Fix test failures The e2e tests have been updated to reference `home-notification` classnames instead of the removed `background-notification`. The active tab proptypes and default values were updated as well.
This commit is contained in:
parent
dadda918b4
commit
9d5be5d29f
@ -208,6 +208,12 @@
|
|||||||
"backToAll": {
|
"backToAll": {
|
||||||
"message": "Back to All"
|
"message": "Back to All"
|
||||||
},
|
},
|
||||||
|
"backupApprovalNotice": {
|
||||||
|
"message": "Backup your Secret Recovery code to keep your wallet and funds secure."
|
||||||
|
},
|
||||||
|
"backupApprovalInfo": {
|
||||||
|
"message": "This secret code is required to recover your wallet in case you lose your device, forget your password, have to re-install MetaMask, or want to access your wallet on another device."
|
||||||
|
},
|
||||||
"backupNow": {
|
"backupNow": {
|
||||||
"message": "Backup now"
|
"message": "Backup now"
|
||||||
},
|
},
|
||||||
@ -550,6 +556,9 @@
|
|||||||
"directDepositEtherExplainer": {
|
"directDepositEtherExplainer": {
|
||||||
"message": "If you already have some Ether, the quickest way to get Ether in your new wallet by direct deposit."
|
"message": "If you already have some Ether, the quickest way to get Ether in your new wallet by direct deposit."
|
||||||
},
|
},
|
||||||
|
"dismiss": {
|
||||||
|
"message": "Dismiss"
|
||||||
|
},
|
||||||
"done": {
|
"done": {
|
||||||
"message": "Done"
|
"message": "Done"
|
||||||
},
|
},
|
||||||
|
@ -24,6 +24,7 @@ class ProviderApprovalController extends SafeEventEmitter {
|
|||||||
this.preferencesController = preferencesController
|
this.preferencesController = preferencesController
|
||||||
this.store = new ObservableStore({
|
this.store = new ObservableStore({
|
||||||
approvedOrigins: {},
|
approvedOrigins: {},
|
||||||
|
dismissedOrigins: {},
|
||||||
providerRequests: [],
|
providerRequests: [],
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -66,7 +67,9 @@ class ProviderApprovalController extends SafeEventEmitter {
|
|||||||
_handleProviderRequest (origin, siteTitle, siteImage) {
|
_handleProviderRequest (origin, siteTitle, siteImage) {
|
||||||
this.store.updateState({ providerRequests: [{ origin, siteTitle, siteImage }] })
|
this.store.updateState({ providerRequests: [{ origin, siteTitle, siteImage }] })
|
||||||
const isUnlocked = this.keyringController.memStore.getState().isUnlocked
|
const isUnlocked = this.keyringController.memStore.getState().isUnlocked
|
||||||
if (this.store.getState().approvedOrigins[origin] && this.caching && isUnlocked) {
|
const { approvedOrigins, dismissedOrigins } = this.store.getState()
|
||||||
|
const originAlreadyHandled = approvedOrigins[origin] || dismissedOrigins[origin]
|
||||||
|
if (originAlreadyHandled && this.caching && isUnlocked) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
this.openPopup && this.openPopup()
|
this.openPopup && this.openPopup()
|
||||||
@ -82,13 +85,21 @@ class ProviderApprovalController extends SafeEventEmitter {
|
|||||||
this.closePopup()
|
this.closePopup()
|
||||||
}
|
}
|
||||||
|
|
||||||
const { approvedOrigins, providerRequests } = this.store.getState()
|
const { approvedOrigins, dismissedOrigins, providerRequests } = this.store.getState()
|
||||||
|
|
||||||
|
let _dismissedOrigins = dismissedOrigins
|
||||||
|
if (dismissedOrigins[origin]) {
|
||||||
|
_dismissedOrigins = Object.assign({}, dismissedOrigins)
|
||||||
|
delete _dismissedOrigins[origin]
|
||||||
|
}
|
||||||
|
|
||||||
const remainingProviderRequests = providerRequests.filter(request => request.origin !== origin)
|
const remainingProviderRequests = providerRequests.filter(request => request.origin !== origin)
|
||||||
this.store.updateState({
|
this.store.updateState({
|
||||||
approvedOrigins: {
|
approvedOrigins: {
|
||||||
...approvedOrigins,
|
...approvedOrigins,
|
||||||
[origin]: true,
|
[origin]: true,
|
||||||
},
|
},
|
||||||
|
dismissedOrigins: _dismissedOrigins,
|
||||||
providerRequests: remainingProviderRequests,
|
providerRequests: remainingProviderRequests,
|
||||||
})
|
})
|
||||||
this.emit(`resolvedRequest:${origin}`, { approved: true })
|
this.emit(`resolvedRequest:${origin}`, { approved: true })
|
||||||
@ -104,7 +115,7 @@ class ProviderApprovalController extends SafeEventEmitter {
|
|||||||
this.closePopup()
|
this.closePopup()
|
||||||
}
|
}
|
||||||
|
|
||||||
const { approvedOrigins, providerRequests } = this.store.getState()
|
const { approvedOrigins, providerRequests, dismissedOrigins } = this.store.getState()
|
||||||
const remainingProviderRequests = providerRequests.filter(request => request.origin !== origin)
|
const remainingProviderRequests = providerRequests.filter(request => request.origin !== origin)
|
||||||
|
|
||||||
// We're cloning and deleting keys here because we don't want to keep unneeded keys
|
// We're cloning and deleting keys here because we don't want to keep unneeded keys
|
||||||
@ -114,6 +125,10 @@ class ProviderApprovalController extends SafeEventEmitter {
|
|||||||
this.store.putState({
|
this.store.putState({
|
||||||
approvedOrigins: _approvedOrigins,
|
approvedOrigins: _approvedOrigins,
|
||||||
providerRequests: remainingProviderRequests,
|
providerRequests: remainingProviderRequests,
|
||||||
|
dismissedOrigins: {
|
||||||
|
...dismissedOrigins,
|
||||||
|
[origin]: true,
|
||||||
|
},
|
||||||
})
|
})
|
||||||
this.emit(`resolvedRequest:${origin}`, { approved: false })
|
this.emit(`resolvedRequest:${origin}`, { approved: false })
|
||||||
}
|
}
|
||||||
@ -124,13 +139,21 @@ class ProviderApprovalController extends SafeEventEmitter {
|
|||||||
* @param {string} origin - origin of the domain that had provider access approved
|
* @param {string} origin - origin of the domain that had provider access approved
|
||||||
*/
|
*/
|
||||||
forceApproveProviderRequestByOrigin (origin) {
|
forceApproveProviderRequestByOrigin (origin) {
|
||||||
const { approvedOrigins, providerRequests } = this.store.getState()
|
const { approvedOrigins, dismissedOrigins, providerRequests } = this.store.getState()
|
||||||
const remainingProviderRequests = providerRequests.filter(request => request.origin !== origin)
|
const remainingProviderRequests = providerRequests.filter(request => request.origin !== origin)
|
||||||
|
|
||||||
|
let _dismissedOrigins = dismissedOrigins
|
||||||
|
if (dismissedOrigins[origin]) {
|
||||||
|
_dismissedOrigins = Object.assign({}, dismissedOrigins)
|
||||||
|
delete _dismissedOrigins[origin]
|
||||||
|
}
|
||||||
|
|
||||||
this.store.updateState({
|
this.store.updateState({
|
||||||
approvedOrigins: {
|
approvedOrigins: {
|
||||||
...approvedOrigins,
|
...approvedOrigins,
|
||||||
[origin]: true,
|
[origin]: true,
|
||||||
},
|
},
|
||||||
|
dismissedOrigins: _dismissedOrigins,
|
||||||
providerRequests: remainingProviderRequests,
|
providerRequests: remainingProviderRequests,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -207,12 +207,12 @@ describe('MetaMask', function () {
|
|||||||
|
|
||||||
describe('backs up the seed phrase', () => {
|
describe('backs up the seed phrase', () => {
|
||||||
it('should show a backup reminder', async () => {
|
it('should show a backup reminder', async () => {
|
||||||
const backupReminder = await findElements(driver, By.css('.backup-notification'))
|
const backupReminder = await findElements(driver, By.xpath("//div[contains(@class, 'home-notification__text') and contains(text(), 'Backup your Secret Recovery code to keep your wallet and funds secure')]"))
|
||||||
assert.equal(backupReminder.length, 1)
|
assert.equal(backupReminder.length, 1)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should take the user to the seedphrase backup screen', async () => {
|
it('should take the user to the seedphrase backup screen', async () => {
|
||||||
const backupButton = await findElement(driver, By.css('.backup-notification__submit-button'))
|
const backupButton = await findElement(driver, By.css('.home-notification__accept-button'))
|
||||||
await backupButton.click()
|
await backupButton.click()
|
||||||
await delay(regularDelayMs)
|
await delay(regularDelayMs)
|
||||||
})
|
})
|
||||||
|
@ -1,50 +0,0 @@
|
|||||||
import React, { PureComponent } from 'react'
|
|
||||||
import PropTypes from 'prop-types'
|
|
||||||
import Button from '../../ui/button'
|
|
||||||
import {
|
|
||||||
INITIALIZE_SEED_PHRASE_ROUTE,
|
|
||||||
} from '../../../helpers/constants/routes'
|
|
||||||
|
|
||||||
export default class BackupNotification extends PureComponent {
|
|
||||||
static propTypes = {
|
|
||||||
history: PropTypes.object,
|
|
||||||
showSeedPhraseBackupAfterOnboarding: PropTypes.func,
|
|
||||||
}
|
|
||||||
|
|
||||||
static contextTypes = {
|
|
||||||
t: PropTypes.func,
|
|
||||||
metricsEvent: PropTypes.func,
|
|
||||||
}
|
|
||||||
|
|
||||||
handleSubmit = () => {
|
|
||||||
const { history, showSeedPhraseBackupAfterOnboarding } = this.props
|
|
||||||
showSeedPhraseBackupAfterOnboarding()
|
|
||||||
history.push(INITIALIZE_SEED_PHRASE_ROUTE)
|
|
||||||
}
|
|
||||||
|
|
||||||
render () {
|
|
||||||
const { t } = this.context
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div className="backup-notification">
|
|
||||||
<div className="backup-notification__header">
|
|
||||||
<img
|
|
||||||
className="backup-notification__icon"
|
|
||||||
src="images/meta-shield.svg"
|
|
||||||
/>
|
|
||||||
<div className="backup-notification__text">Backup your Secret Recovery code to keep your wallet and funds secure.</div>
|
|
||||||
<i className="fa fa-info-circle"></i>
|
|
||||||
</div>
|
|
||||||
<div className="backup-notification__buttons">
|
|
||||||
<Button
|
|
||||||
type="primary"
|
|
||||||
className="backup-notification__submit-button"
|
|
||||||
onClick={this.handleSubmit}
|
|
||||||
>
|
|
||||||
{ t('backupNow') }
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,16 +0,0 @@
|
|||||||
import { connect } from 'react-redux'
|
|
||||||
import { withRouter } from 'react-router-dom'
|
|
||||||
import { compose } from 'recompose'
|
|
||||||
import BackupNotification from './backup-notification.component'
|
|
||||||
import { showSeedPhraseBackupAfterOnboarding } from '../../../store/actions'
|
|
||||||
|
|
||||||
const mapDispatchToProps = dispatch => {
|
|
||||||
return {
|
|
||||||
showSeedPhraseBackupAfterOnboarding: () => dispatch(showSeedPhraseBackupAfterOnboarding()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default compose(
|
|
||||||
withRouter,
|
|
||||||
connect(null, mapDispatchToProps)
|
|
||||||
)(BackupNotification)
|
|
@ -1 +0,0 @@
|
|||||||
export { default } from './backup-notification.container'
|
|
@ -1,75 +0,0 @@
|
|||||||
.backup-notification {
|
|
||||||
background: rgba(36, 41, 46, 0.9);
|
|
||||||
box-shadow: 0px 2px 10px rgba(0, 0, 0, 0.12);
|
|
||||||
border-radius: 8px;
|
|
||||||
height: 116px;
|
|
||||||
padding: 16px;
|
|
||||||
margin: 8px;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-flow: column;
|
|
||||||
justify-content: space-between;
|
|
||||||
|
|
||||||
position: absolute;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
|
|
||||||
&__header {
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__text {
|
|
||||||
font-family: Roboto;
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: normal;
|
|
||||||
font-size: 12px;
|
|
||||||
color: #FFFFFF;
|
|
||||||
margin-left: 10px;
|
|
||||||
margin-right: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.fa-info-circle {
|
|
||||||
color: #6A737D;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__ignore-button {
|
|
||||||
border: 2px solid #6A737D;
|
|
||||||
box-sizing: border-box;
|
|
||||||
border-radius: 6px;
|
|
||||||
color: $white;
|
|
||||||
background-color: rgba(36, 41, 46, 0.9);
|
|
||||||
height: 34px;
|
|
||||||
width: 155px;
|
|
||||||
padding: 0;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
border-color: #6A737D;
|
|
||||||
background-color: #6A737D;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__submit-button {
|
|
||||||
border: 2px solid #6A737D;
|
|
||||||
box-sizing: border-box;
|
|
||||||
border-radius: 6px;
|
|
||||||
color: $white;
|
|
||||||
background-color: rgba(36, 41, 46, 0.9);
|
|
||||||
height: 34px;
|
|
||||||
width: 155px;
|
|
||||||
padding: 0;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background-color: #3b4046;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:active {
|
|
||||||
background-color:#141618;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__buttons {
|
|
||||||
display: flex;
|
|
||||||
width: 130px;
|
|
||||||
align-self: flex-end;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,4 +1,5 @@
|
|||||||
import React, { PureComponent } from 'react'
|
import React, { PureComponent } from 'react'
|
||||||
|
import classnames from 'classnames'
|
||||||
import {Tooltip as ReactTippy} from 'react-tippy'
|
import {Tooltip as ReactTippy} from 'react-tippy'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import Button from '../../ui/button'
|
import Button from '../../ui/button'
|
||||||
@ -22,6 +23,7 @@ export default class HomeNotification extends PureComponent {
|
|||||||
onIgnore: PropTypes.func,
|
onIgnore: PropTypes.func,
|
||||||
descriptionText: PropTypes.string.isRequired,
|
descriptionText: PropTypes.string.isRequired,
|
||||||
infoText: PropTypes.string,
|
infoText: PropTypes.string,
|
||||||
|
classNames: PropTypes.array,
|
||||||
}
|
}
|
||||||
|
|
||||||
handleAccept = () => {
|
handleAccept = () => {
|
||||||
@ -33,10 +35,10 @@ export default class HomeNotification extends PureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { descriptionText, acceptText, onAccept, ignoreText, onIgnore, infoText } = this.props
|
const { descriptionText, acceptText, onAccept, ignoreText, onIgnore, infoText, classNames = [] } = this.props
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="home-notification">
|
<div className={classnames('home-notification', ...classNames)}>
|
||||||
<div className="home-notification__header">
|
<div className="home-notification__header">
|
||||||
<div className="home-notification__header-container">
|
<div className="home-notification__header-container">
|
||||||
<img
|
<img
|
||||||
|
@ -10,7 +10,10 @@
|
|||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
height: 116px;
|
height: 116px;
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
margin: 8px;
|
|
||||||
|
@media screen and (min-width: 576px) {
|
||||||
|
min-width: 472px;
|
||||||
|
}
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-flow: column;
|
flex-flow: column;
|
||||||
@ -50,6 +53,10 @@
|
|||||||
width: 155px;
|
width: 155px;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
|
||||||
|
@media screen and (max-width: 575px) {
|
||||||
|
width: 135px;
|
||||||
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
border-color: #6A737D;
|
border-color: #6A737D;
|
||||||
background-color: #6A737D;
|
background-color: #6A737D;
|
||||||
@ -69,6 +76,11 @@
|
|||||||
height: 34px;
|
height: 34px;
|
||||||
width: 155px;
|
width: 155px;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
margin-left: 4px;
|
||||||
|
|
||||||
|
@media screen and (max-width: 575px) {
|
||||||
|
width: 135px;
|
||||||
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
border-color: #6A737D;
|
border-color: #6A737D;
|
||||||
@ -83,7 +95,7 @@
|
|||||||
&__buttons {
|
&__buttons {
|
||||||
display: flex;
|
display: flex;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
justify-content: space-between;
|
justify-content: flex-start;
|
||||||
flex-direction: row-reverse;
|
flex-direction: row-reverse;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -84,4 +84,4 @@
|
|||||||
|
|
||||||
@import 'home-notification/index';
|
@import 'home-notification/index';
|
||||||
|
|
||||||
@import 'backup-notification/index';
|
@import 'multiple-notifications/index';
|
||||||
|
1
ui/app/components/app/multiple-notifications/index.js
Normal file
1
ui/app/components/app/multiple-notifications/index.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { default } from './multiple-notifications.component'
|
80
ui/app/components/app/multiple-notifications/index.scss
Normal file
80
ui/app/components/app/multiple-notifications/index.scss
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
.home-notification-wrapper--show-all,
|
||||||
|
.home-notification-wrapper--show-first {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
width: 472px;
|
||||||
|
height: 116px;
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
margin: 8px;
|
||||||
|
|
||||||
|
@media screen and (max-width: 576px) {
|
||||||
|
width: 340px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.home-notification-wrapper__i-container {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
visibility: none;
|
||||||
|
|
||||||
|
.fa-sm {
|
||||||
|
display: initial;
|
||||||
|
position: absolute;
|
||||||
|
bottom: 14px;
|
||||||
|
left: 16px;
|
||||||
|
color: white;
|
||||||
|
cursor: pointer;
|
||||||
|
visibility: visible;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: #b0d7f2;
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.home-notification-wrapper--show-all {
|
||||||
|
height: 356px;;
|
||||||
|
justify-content: flex-end;
|
||||||
|
margin-bottom: 0;
|
||||||
|
|
||||||
|
.home-notification-wrapper__i-container {
|
||||||
|
height: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
> div {
|
||||||
|
position: relative;
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fa-sm {
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.home-notification-wrapper--show-first {
|
||||||
|
> div {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
> div:first-of-type {
|
||||||
|
visibility: visible;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.fa-sm {
|
||||||
|
position: relative;
|
||||||
|
display: initial;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.flipped {
|
||||||
|
transform: rotate(180deg);
|
||||||
|
}
|
@ -0,0 +1,39 @@
|
|||||||
|
import React, { PureComponent } from 'react'
|
||||||
|
import classnames from 'classnames'
|
||||||
|
import PropTypes from 'prop-types'
|
||||||
|
|
||||||
|
export default class MultipleNotifications extends PureComponent {
|
||||||
|
static propTypes = {
|
||||||
|
notifications: PropTypes.array,
|
||||||
|
classNames: PropTypes.array,
|
||||||
|
}
|
||||||
|
|
||||||
|
state = {
|
||||||
|
showAll: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
render () {
|
||||||
|
const { showAll } = this.state
|
||||||
|
const { notifications, classNames = [] } = this.props
|
||||||
|
|
||||||
|
return (<div
|
||||||
|
className={classnames(...classNames, {
|
||||||
|
'home-notification-wrapper--show-all': showAll,
|
||||||
|
'home-notification-wrapper--show-first': !showAll,
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
{notifications
|
||||||
|
.filter(notificationConfig => notificationConfig.shouldBeRendered)
|
||||||
|
.map(notificationConfig => notificationConfig.component)
|
||||||
|
}
|
||||||
|
<div
|
||||||
|
className="home-notification-wrapper__i-container"
|
||||||
|
onClick={() => this.setState({ showAll: !showAll })}
|
||||||
|
>
|
||||||
|
{notifications.length > 1 ? <i className={classnames('fa fa-sm fa-sort-amount-asc', {
|
||||||
|
'flipped': !showAll,
|
||||||
|
})} /> : null}
|
||||||
|
</div>
|
||||||
|
</div>)
|
||||||
|
}
|
||||||
|
}
|
@ -130,3 +130,14 @@ input.form-control {
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.pinned-to-bottom {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pinned-to-bottom-right {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0px;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
@ -3,15 +3,16 @@ import PropTypes from 'prop-types'
|
|||||||
import Media from 'react-media'
|
import Media from 'react-media'
|
||||||
import { Redirect } from 'react-router-dom'
|
import { Redirect } from 'react-router-dom'
|
||||||
import HomeNotification from '../../components/app/home-notification'
|
import HomeNotification from '../../components/app/home-notification'
|
||||||
|
import MultipleNotifications from '../../components/app/multiple-notifications'
|
||||||
import WalletView from '../../components/app/wallet-view'
|
import WalletView from '../../components/app/wallet-view'
|
||||||
import TransactionView from '../../components/app/transaction-view'
|
import TransactionView from '../../components/app/transaction-view'
|
||||||
import ProviderApproval from '../provider-approval'
|
import ProviderApproval from '../provider-approval'
|
||||||
import BackupNotification from '../../components/app/backup-notification'
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
RESTORE_VAULT_ROUTE,
|
RESTORE_VAULT_ROUTE,
|
||||||
CONFIRM_TRANSACTION_ROUTE,
|
CONFIRM_TRANSACTION_ROUTE,
|
||||||
CONFIRM_ADD_SUGGESTED_TOKEN_ROUTE,
|
CONFIRM_ADD_SUGGESTED_TOKEN_ROUTE,
|
||||||
|
INITIALIZE_SEED_PHRASE_ROUTE,
|
||||||
} from '../../helpers/constants/routes'
|
} from '../../helpers/constants/routes'
|
||||||
|
|
||||||
export default class Home extends PureComponent {
|
export default class Home extends PureComponent {
|
||||||
@ -20,15 +21,17 @@ export default class Home extends PureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
activeTab: null,
|
activeTab: {},
|
||||||
unsetMigratedPrivacyMode: null,
|
unsetMigratedPrivacyMode: null,
|
||||||
forceApproveProviderRequestByOrigin: null,
|
forceApproveProviderRequestByOrigin: null,
|
||||||
}
|
}
|
||||||
|
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
activeTab: PropTypes.shape({
|
activeTab: PropTypes.shape({
|
||||||
title: PropTypes.string.isRequired,
|
origin: PropTypes.string,
|
||||||
url: PropTypes.string.isRequired,
|
protocol: PropTypes.string,
|
||||||
|
title: PropTypes.string,
|
||||||
|
url: PropTypes.string,
|
||||||
}),
|
}),
|
||||||
history: PropTypes.object,
|
history: PropTypes.object,
|
||||||
forgottenPassword: PropTypes.bool,
|
forgottenPassword: PropTypes.bool,
|
||||||
@ -40,6 +43,8 @@ export default class Home extends PureComponent {
|
|||||||
viewingUnconnectedDapp: PropTypes.bool.isRequired,
|
viewingUnconnectedDapp: PropTypes.bool.isRequired,
|
||||||
forceApproveProviderRequestByOrigin: PropTypes.func,
|
forceApproveProviderRequestByOrigin: PropTypes.func,
|
||||||
shouldShowSeedPhraseReminder: PropTypes.bool,
|
shouldShowSeedPhraseReminder: PropTypes.bool,
|
||||||
|
showSeedPhraseBackupAfterOnboarding: PropTypes.bool,
|
||||||
|
rejectProviderRequestByOrigin: PropTypes.func,
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillMount () {
|
componentWillMount () {
|
||||||
@ -77,6 +82,8 @@ export default class Home extends PureComponent {
|
|||||||
viewingUnconnectedDapp,
|
viewingUnconnectedDapp,
|
||||||
forceApproveProviderRequestByOrigin,
|
forceApproveProviderRequestByOrigin,
|
||||||
shouldShowSeedPhraseReminder,
|
shouldShowSeedPhraseReminder,
|
||||||
|
showSeedPhraseBackupAfterOnboarding,
|
||||||
|
rejectProviderRequestByOrigin,
|
||||||
} = this.props
|
} = this.props
|
||||||
|
|
||||||
if (forgottenPassword) {
|
if (forgottenPassword) {
|
||||||
@ -98,39 +105,49 @@ export default class Home extends PureComponent {
|
|||||||
{ !history.location.pathname.match(/^\/confirm-transaction/)
|
{ !history.location.pathname.match(/^\/confirm-transaction/)
|
||||||
? (
|
? (
|
||||||
<TransactionView>
|
<TransactionView>
|
||||||
{
|
<MultipleNotifications
|
||||||
showPrivacyModeNotification
|
className
|
||||||
? (
|
notifications={[
|
||||||
<HomeNotification
|
{
|
||||||
|
shouldBeRendered: showPrivacyModeNotification,
|
||||||
|
component: <HomeNotification
|
||||||
descriptionText={t('privacyModeDefault')}
|
descriptionText={t('privacyModeDefault')}
|
||||||
acceptText={t('learnMore')}
|
acceptText={t('learnMore')}
|
||||||
onAccept={() => {
|
onAccept={() => {
|
||||||
window.open('https://medium.com/metamask/42549d4870fa', '_blank', 'noopener')
|
window.open('https://medium.com/metamask/42549d4870fa', '_blank', 'noopener')
|
||||||
unsetMigratedPrivacyMode()
|
unsetMigratedPrivacyMode()
|
||||||
}}
|
}}
|
||||||
/>
|
key="home-privacyModeDefault"
|
||||||
)
|
/>,
|
||||||
: null
|
},
|
||||||
}
|
{
|
||||||
{
|
shouldBeRendered: viewingUnconnectedDapp,
|
||||||
viewingUnconnectedDapp
|
component: <HomeNotification
|
||||||
? (
|
|
||||||
<HomeNotification
|
|
||||||
descriptionText={t('shareAddressToConnect', [activeTab.origin])}
|
descriptionText={t('shareAddressToConnect', [activeTab.origin])}
|
||||||
acceptText={t('shareAddress')}
|
acceptText={t('shareAddress')}
|
||||||
onAccept={() => {
|
onAccept={() => {
|
||||||
forceApproveProviderRequestByOrigin(activeTab.origin)
|
forceApproveProviderRequestByOrigin(activeTab.origin)
|
||||||
}}
|
}}
|
||||||
|
ignoreText={t('dismiss')}
|
||||||
|
onIgnore={() => rejectProviderRequestByOrigin(activeTab.origin)}
|
||||||
infoText={t('shareAddressInfo', [activeTab.origin])}
|
infoText={t('shareAddressInfo', [activeTab.origin])}
|
||||||
/>
|
key="home-shareAddressToConnect"
|
||||||
)
|
/>,
|
||||||
: null
|
},
|
||||||
}
|
{
|
||||||
{
|
shouldBeRendered: shouldShowSeedPhraseReminder,
|
||||||
shouldShowSeedPhraseReminder
|
component: <HomeNotification
|
||||||
? (<BackupNotification />)
|
descriptionText={t('backupApprovalNotice')}
|
||||||
: null
|
acceptText={t('backupNow')}
|
||||||
}
|
onAccept={() => {
|
||||||
|
showSeedPhraseBackupAfterOnboarding()
|
||||||
|
history.push(INITIALIZE_SEED_PHRASE_ROUTE)
|
||||||
|
}}
|
||||||
|
infoText={t('backupApprovalInfo')}
|
||||||
|
key="home-backupApprovalNotice"
|
||||||
|
/>,
|
||||||
|
},
|
||||||
|
]}/>
|
||||||
</TransactionView>
|
</TransactionView>
|
||||||
)
|
)
|
||||||
: null }
|
: null }
|
||||||
|
@ -7,6 +7,8 @@ import { getCurrentEthBalance } from '../../selectors/selectors'
|
|||||||
import {
|
import {
|
||||||
forceApproveProviderRequestByOrigin,
|
forceApproveProviderRequestByOrigin,
|
||||||
unsetMigratedPrivacyMode,
|
unsetMigratedPrivacyMode,
|
||||||
|
showSeedPhraseBackupAfterOnboarding,
|
||||||
|
rejectProviderRequestByOrigin,
|
||||||
} from '../../store/actions'
|
} from '../../store/actions'
|
||||||
import { getEnvironmentType } from '../../../../app/scripts/lib/util'
|
import { getEnvironmentType } from '../../../../app/scripts/lib/util'
|
||||||
import { ENVIRONMENT_TYPE_POPUP } from '../../../../app/scripts/lib/enums'
|
import { ENVIRONMENT_TYPE_POPUP } from '../../../../app/scripts/lib/enums'
|
||||||
@ -17,6 +19,7 @@ const mapStateToProps = state => {
|
|||||||
const { activeTab, metamask, appState } = state
|
const { activeTab, metamask, appState } = state
|
||||||
const {
|
const {
|
||||||
approvedOrigins,
|
approvedOrigins,
|
||||||
|
dismissedOrigins,
|
||||||
lostAccounts,
|
lostAccounts,
|
||||||
suggestedTokens,
|
suggestedTokens,
|
||||||
providerRequests,
|
providerRequests,
|
||||||
@ -34,7 +37,8 @@ const mapStateToProps = state => {
|
|||||||
activeTab &&
|
activeTab &&
|
||||||
activeTabDappProtocols.includes(activeTab.protocol) &&
|
activeTabDappProtocols.includes(activeTab.protocol) &&
|
||||||
privacyMode &&
|
privacyMode &&
|
||||||
!approvedOrigins[activeTab.origin]
|
!approvedOrigins[activeTab.origin] &&
|
||||||
|
!dismissedOrigins[activeTab.origin]
|
||||||
)
|
)
|
||||||
const isPopup = getEnvironmentType(window.location.href) === ENVIRONMENT_TYPE_POPUP
|
const isPopup = getEnvironmentType(window.location.href) === ENVIRONMENT_TYPE_POPUP
|
||||||
|
|
||||||
@ -48,12 +52,15 @@ const mapStateToProps = state => {
|
|||||||
activeTab,
|
activeTab,
|
||||||
viewingUnconnectedDapp: isUnconnected && isPopup,
|
viewingUnconnectedDapp: isUnconnected && isPopup,
|
||||||
shouldShowSeedPhraseReminder: !seedPhraseBackedUp && (parseInt(accountBalance, 16) > 0 || tokens.length > 0),
|
shouldShowSeedPhraseReminder: !seedPhraseBackedUp && (parseInt(accountBalance, 16) > 0 || tokens.length > 0),
|
||||||
|
isPopup,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch) => ({
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
unsetMigratedPrivacyMode: () => dispatch(unsetMigratedPrivacyMode()),
|
unsetMigratedPrivacyMode: () => dispatch(unsetMigratedPrivacyMode()),
|
||||||
forceApproveProviderRequestByOrigin: (origin) => dispatch(forceApproveProviderRequestByOrigin(origin)),
|
forceApproveProviderRequestByOrigin: (origin) => dispatch(forceApproveProviderRequestByOrigin(origin)),
|
||||||
|
rejectProviderRequestByOrigin: origin => dispatch(rejectProviderRequestByOrigin(origin)),
|
||||||
|
showSeedPhraseBackupAfterOnboarding: () => dispatch(showSeedPhraseBackupAfterOnboarding()),
|
||||||
})
|
})
|
||||||
|
|
||||||
export default compose(
|
export default compose(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user