mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
Make permission approval redirect flow consistent (#8755)
* make redirect flow consistent * remove cancel redirect * extract redirect component into own file
This commit is contained in:
commit
1323233cfa
@ -73,12 +73,6 @@
|
|||||||
"showIncomingTransactionsDescription": {
|
"showIncomingTransactionsDescription": {
|
||||||
"message": "Select this to use Etherscan to show incoming transactions in the transactions list"
|
"message": "Select this to use Etherscan to show incoming transactions in the transactions list"
|
||||||
},
|
},
|
||||||
"cancelling": {
|
|
||||||
"message": "Cancelling..."
|
|
||||||
},
|
|
||||||
"cancelledConnectionWithMetaMask": {
|
|
||||||
"message": "Cancelled Connection With MetaMask"
|
|
||||||
},
|
|
||||||
"chartOnlyAvailableEth": {
|
"chartOnlyAvailableEth": {
|
||||||
"message": "Chart only available on Ethereum networks."
|
"message": "Chart only available on Ethereum networks."
|
||||||
},
|
},
|
||||||
@ -88,9 +82,6 @@
|
|||||||
"connectWithMetaMask": {
|
"connectWithMetaMask": {
|
||||||
"message": "Connect With MetaMask"
|
"message": "Connect With MetaMask"
|
||||||
},
|
},
|
||||||
"connectingWithMetaMask": {
|
|
||||||
"message": "Connecting With MetaMask..."
|
|
||||||
},
|
|
||||||
"connectTo": {
|
"connectTo": {
|
||||||
"message": "Connect to $1",
|
"message": "Connect to $1",
|
||||||
"description": "$1 is the name/origin of a site/dapp that the user can connect to metamask"
|
"description": "$1 is the name/origin of a site/dapp that the user can connect to metamask"
|
||||||
|
@ -5,18 +5,12 @@
|
|||||||
"showIncomingTransactionsDescription": {
|
"showIncomingTransactionsDescription": {
|
||||||
"message": "Usa Etherscan per visualizzare le transazioni in ingresso nella lista delle transazioni"
|
"message": "Usa Etherscan per visualizzare le transazioni in ingresso nella lista delle transazioni"
|
||||||
},
|
},
|
||||||
"cancelledConnectionWithMetaMask": {
|
|
||||||
"message": "Transazioni Annullate con MetaMask"
|
|
||||||
},
|
|
||||||
"chartOnlyAvailableEth": {
|
"chartOnlyAvailableEth": {
|
||||||
"message": "Grafico disponibile solo per le reti Ethereum."
|
"message": "Grafico disponibile solo per le reti Ethereum."
|
||||||
},
|
},
|
||||||
"connectedSites": {
|
"connectedSites": {
|
||||||
"message": "Siti connessi"
|
"message": "Siti connessi"
|
||||||
},
|
},
|
||||||
"connectingWithMetaMask": {
|
|
||||||
"message": "Connettendo con MetaMask..."
|
|
||||||
},
|
|
||||||
"connectTo": {
|
"connectTo": {
|
||||||
"message": "Collegati a $1",
|
"message": "Collegati a $1",
|
||||||
"description": "$1 is the name/origin of a site/dapp that the user can connect to metamask"
|
"description": "$1 is the name/origin of a site/dapp that the user can connect to metamask"
|
||||||
|
@ -46,15 +46,6 @@
|
|||||||
padding-left: 24px;
|
padding-left: 24px;
|
||||||
padding-right: 24px;
|
padding-right: 24px;
|
||||||
|
|
||||||
&--redirect {
|
|
||||||
margin-top: 140px;
|
|
||||||
width: 100%;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
padding-top: 8px;
|
|
||||||
height: 144px;
|
|
||||||
}
|
|
||||||
|
|
||||||
a, a:hover {
|
a, a:hover {
|
||||||
color: $dodger-blue;
|
color: $dodger-blue;
|
||||||
}
|
}
|
||||||
@ -94,10 +85,6 @@
|
|||||||
@extend %content-text;
|
@extend %content-text;
|
||||||
line-height: 20px;
|
line-height: 20px;
|
||||||
color: #6A737D;
|
color: #6A737D;
|
||||||
|
|
||||||
&--redirect {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&__permissions-container {
|
&__permissions-container {
|
||||||
@ -147,105 +134,3 @@
|
|||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.permission-result {
|
|
||||||
@extend %header--24;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
text-align: center;
|
|
||||||
color: $Black-100;
|
|
||||||
|
|
||||||
&__icons {
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__center-icon {
|
|
||||||
display: flex;
|
|
||||||
position: relative;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
font-size: 14px;
|
|
||||||
line-height: 18px;
|
|
||||||
padding: 8px 0 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
h2 {
|
|
||||||
font-size: 12px;
|
|
||||||
line-height: 17px;
|
|
||||||
color: #6A737D;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__check {
|
|
||||||
width: 40px;
|
|
||||||
height: 40px;
|
|
||||||
background: white url("/images/permissions-check.svg") no-repeat;
|
|
||||||
position: absolute;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__reject {
|
|
||||||
position: absolute;
|
|
||||||
background: white;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
|
|
||||||
i {
|
|
||||||
color: #D73A49;
|
|
||||||
transform: scale(3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__identicon, .icon-with-fallback__identicon {
|
|
||||||
width: 32px;
|
|
||||||
height: 32px;
|
|
||||||
|
|
||||||
&--default {
|
|
||||||
background-color: #777A87;
|
|
||||||
color: white;
|
|
||||||
width: 64px;
|
|
||||||
height: 64px;
|
|
||||||
border-radius: 32px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&__identicon-container, .icon-with-fallback__identicon-container {
|
|
||||||
height: auto;
|
|
||||||
position: relative;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
height: 64px;
|
|
||||||
width: 64px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__identicon-border, .icon-with-fallback__identicon-border {
|
|
||||||
height: 64px;
|
|
||||||
width: 64px;
|
|
||||||
border-radius: 50%;
|
|
||||||
border: 1px solid white;
|
|
||||||
background: #FFFFFF;
|
|
||||||
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.25);
|
|
||||||
}
|
|
||||||
|
|
||||||
&__identicon-border {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.icon-with-fallback__identicon-border {
|
|
||||||
position: absolute;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import React, { PureComponent } from 'react'
|
import React, { PureComponent } from 'react'
|
||||||
import IconWithFallBack from '../../../ui/icon-with-fallback'
|
|
||||||
import PermissionsConnectHeader from '../../permissions-connect-header'
|
import PermissionsConnectHeader from '../../permissions-connect-header'
|
||||||
import Tooltip from '../../../ui/tooltip-v2'
|
import Tooltip from '../../../ui/tooltip-v2'
|
||||||
import classnames from 'classnames'
|
|
||||||
|
|
||||||
export default class PermissionPageContainerContent extends PureComponent {
|
export default class PermissionPageContainerContent extends PureComponent {
|
||||||
|
|
||||||
@ -13,13 +11,9 @@ export default class PermissionPageContainerContent extends PureComponent {
|
|||||||
onPermissionToggle: PropTypes.func.isRequired,
|
onPermissionToggle: PropTypes.func.isRequired,
|
||||||
selectedIdentities: PropTypes.array,
|
selectedIdentities: PropTypes.array,
|
||||||
allIdentitiesSelected: PropTypes.bool,
|
allIdentitiesSelected: PropTypes.bool,
|
||||||
redirect: PropTypes.bool,
|
|
||||||
permissionRejected: PropTypes.bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
redirect: null,
|
|
||||||
permissionRejected: null,
|
|
||||||
selectedIdentities: [],
|
selectedIdentities: [],
|
||||||
allIdentitiesSelected: false,
|
allIdentitiesSelected: false,
|
||||||
}
|
}
|
||||||
@ -28,39 +22,6 @@ export default class PermissionPageContainerContent extends PureComponent {
|
|||||||
t: PropTypes.func,
|
t: PropTypes.func,
|
||||||
}
|
}
|
||||||
|
|
||||||
renderBrokenLine () {
|
|
||||||
return (
|
|
||||||
<svg width="131" height="2" viewBox="0 0 131 2" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path d="M0 1H134" stroke="#CDD1E4" strokeLinejoin="round" strokeDasharray="8 7" />
|
|
||||||
</svg>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
renderRedirect () {
|
|
||||||
const { t } = this.context
|
|
||||||
const { permissionRejected, domainMetadata } = this.props
|
|
||||||
return (
|
|
||||||
<div className="permission-result">
|
|
||||||
{ permissionRejected ? t('cancelling') : t('connecting') }
|
|
||||||
<div className="permission-result__icons">
|
|
||||||
<IconWithFallBack icon={domainMetadata.icon} name={domainMetadata.name} />
|
|
||||||
<div className="permission-result__center-icon">
|
|
||||||
{ permissionRejected
|
|
||||||
? <span className="permission-result__reject" ><i className="fa fa-times-circle" /></span>
|
|
||||||
: <span className="permission-result__check" />
|
|
||||||
}
|
|
||||||
{ this.renderBrokenLine() }
|
|
||||||
</div>
|
|
||||||
<div className="permission-result__identicon-container">
|
|
||||||
<div className="permission-result__identicon-border">
|
|
||||||
<img src="/images/logo/metamask-fox.svg" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
renderRequestedPermissions () {
|
renderRequestedPermissions () {
|
||||||
const {
|
const {
|
||||||
selectedPermissions, onPermissionToggle,
|
selectedPermissions, onPermissionToggle,
|
||||||
@ -134,14 +95,10 @@ export default class PermissionPageContainerContent extends PureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getTitle () {
|
getTitle () {
|
||||||
const { domainMetadata, redirect, permissionRejected, selectedIdentities, allIdentitiesSelected } = this.props
|
const { domainMetadata, selectedIdentities, allIdentitiesSelected } = this.props
|
||||||
const { t } = this.context
|
const { t } = this.context
|
||||||
|
|
||||||
if (redirect && permissionRejected) {
|
if (domainMetadata.extensionId) {
|
||||||
return t('cancelledConnectionWithMetaMask')
|
|
||||||
} else if (redirect) {
|
|
||||||
return t('connectingWithMetaMask')
|
|
||||||
} else if (domainMetadata.extensionId) {
|
|
||||||
return t('externalExtension', [domainMetadata.extensionId])
|
return t('externalExtension', [domainMetadata.extensionId])
|
||||||
} else if (allIdentitiesSelected) {
|
} else if (allIdentitiesSelected) {
|
||||||
return t(
|
return t(
|
||||||
@ -166,36 +123,27 @@ export default class PermissionPageContainerContent extends PureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { domainMetadata, redirect } = this.props
|
const { domainMetadata } = this.props
|
||||||
const { t } = this.context
|
const { t } = this.context
|
||||||
|
|
||||||
const title = this.getTitle()
|
const title = this.getTitle()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div className="permission-approval-container__content">
|
||||||
className={classnames('permission-approval-container__content', {
|
<div className="permission-approval-container__content-container">
|
||||||
'permission-approval-container__content--redirect': redirect,
|
<PermissionsConnectHeader
|
||||||
})}
|
icon={domainMetadata.icon}
|
||||||
>
|
iconName={domainMetadata.origin}
|
||||||
{ !redirect
|
headerTitle={title}
|
||||||
? (
|
headerText={ domainMetadata.extensionId
|
||||||
<div className="permission-approval-container__content-container">
|
? t('allowExternalExtensionTo', [domainMetadata.extensionId])
|
||||||
<PermissionsConnectHeader
|
: t('allowThisSiteTo')
|
||||||
icon={domainMetadata.icon}
|
}
|
||||||
iconName={domainMetadata.origin}
|
/>
|
||||||
headerTitle={title}
|
<section className="permission-approval-container__permissions-container">
|
||||||
headerText={ domainMetadata.extensionId
|
{ this.renderRequestedPermissions() }
|
||||||
? t('allowExternalExtensionTo', [domainMetadata.extensionId])
|
</section>
|
||||||
: t('allowThisSiteTo')
|
</div>
|
||||||
}
|
|
||||||
/>
|
|
||||||
<section className="permission-approval-container__permissions-container">
|
|
||||||
{ this.renderRequestedPermissions() }
|
|
||||||
</section>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
: this.renderRedirect()
|
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -13,15 +13,11 @@ export default class PermissionPageContainer extends Component {
|
|||||||
selectedIdentities: PropTypes.array,
|
selectedIdentities: PropTypes.array,
|
||||||
allIdentitiesSelected: PropTypes.bool,
|
allIdentitiesSelected: PropTypes.bool,
|
||||||
request: PropTypes.object,
|
request: PropTypes.object,
|
||||||
redirect: PropTypes.bool,
|
|
||||||
permissionRejected: PropTypes.bool,
|
|
||||||
requestMetadata: PropTypes.object,
|
requestMetadata: PropTypes.object,
|
||||||
targetDomainMetadata: PropTypes.object.isRequired,
|
targetDomainMetadata: PropTypes.object.isRequired,
|
||||||
}
|
}
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
redirect: null,
|
|
||||||
permissionRejected: null,
|
|
||||||
request: {},
|
request: {},
|
||||||
requestMetadata: {},
|
requestMetadata: {},
|
||||||
selectedIdentities: [],
|
selectedIdentities: [],
|
||||||
@ -116,8 +112,6 @@ export default class PermissionPageContainer extends Component {
|
|||||||
requestMetadata,
|
requestMetadata,
|
||||||
targetDomainMetadata,
|
targetDomainMetadata,
|
||||||
selectedIdentities,
|
selectedIdentities,
|
||||||
redirect,
|
|
||||||
permissionRejected,
|
|
||||||
allIdentitiesSelected,
|
allIdentitiesSelected,
|
||||||
} = this.props
|
} = this.props
|
||||||
|
|
||||||
@ -129,27 +123,20 @@ export default class PermissionPageContainer extends Component {
|
|||||||
selectedPermissions={this.state.selectedPermissions}
|
selectedPermissions={this.state.selectedPermissions}
|
||||||
onPermissionToggle={this.onPermissionToggle}
|
onPermissionToggle={this.onPermissionToggle}
|
||||||
selectedIdentities={selectedIdentities}
|
selectedIdentities={selectedIdentities}
|
||||||
redirect={redirect}
|
|
||||||
permissionRejected={permissionRejected}
|
|
||||||
allIdentitiesSelected={allIdentitiesSelected}
|
allIdentitiesSelected={allIdentitiesSelected}
|
||||||
/>
|
/>
|
||||||
{ !redirect
|
<div className="permission-approval-container__footers">
|
||||||
? (
|
<PermissionsConnectFooter />
|
||||||
<div className="permission-approval-container__footers">
|
<PageContainerFooter
|
||||||
<PermissionsConnectFooter />
|
cancelButtonType="default"
|
||||||
<PageContainerFooter
|
onCancel={() => this.onCancel()}
|
||||||
cancelButtonType="default"
|
cancelText={this.context.t('cancel')}
|
||||||
onCancel={() => this.onCancel()}
|
onSubmit={() => this.onSubmit()}
|
||||||
cancelText={this.context.t('cancel')}
|
submitText={this.context.t('connect')}
|
||||||
onSubmit={() => this.onSubmit()}
|
submitButtonType="confirm"
|
||||||
submitText={this.context.t('connect')}
|
buttonSizeLarge={false}
|
||||||
submitButtonType="confirm"
|
/>
|
||||||
buttonSizeLarge={false}
|
</div>
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
: null
|
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -5,13 +5,14 @@ import IconWithFallBack from '../../ui/icon-with-fallback'
|
|||||||
export default class PermissionsConnectHeader extends Component {
|
export default class PermissionsConnectHeader extends Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
icon: PropTypes.string,
|
icon: PropTypes.string,
|
||||||
iconName: PropTypes.string.isRequired,
|
iconName: PropTypes.string,
|
||||||
headerTitle: PropTypes.node,
|
headerTitle: PropTypes.node,
|
||||||
headerText: PropTypes.string,
|
headerText: PropTypes.string,
|
||||||
}
|
}
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
icon: null,
|
icon: null,
|
||||||
|
iconName: '',
|
||||||
headerTitle: '',
|
headerTitle: '',
|
||||||
headerText: '',
|
headerText: '',
|
||||||
}
|
}
|
||||||
|
@ -198,23 +198,23 @@ export default class ChooseAccount extends Component {
|
|||||||
: t('connectAccountOrCreate')
|
: t('connectAccountOrCreate')
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
{ this.renderAccountsListHeader() }
|
{this.renderAccountsListHeader()}
|
||||||
{ this.renderAccountsList() }
|
{this.renderAccountsList()}
|
||||||
<div className="permissions-connect-choose-account__footer-container">
|
<div className="permissions-connect-choose-account__footer-container">
|
||||||
<PermissionsConnectFooter />
|
<PermissionsConnectFooter />
|
||||||
<div className="permissions-connect-choose-account__bottom-buttons">
|
<div className="permissions-connect-choose-account__bottom-buttons">
|
||||||
<Button
|
<Button
|
||||||
onClick={ () => cancelPermissionsRequest(permissionsRequestId) }
|
onClick={() => cancelPermissionsRequest(permissionsRequestId)}
|
||||||
type="default"
|
type="default"
|
||||||
>
|
>
|
||||||
{ t('cancel') }
|
{t('cancel')}
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
onClick={ () => selectAccounts(selectedAccounts) }
|
onClick={() => selectAccounts(selectedAccounts)}
|
||||||
type="primary"
|
type="primary"
|
||||||
disabled={ selectedAccounts.size === 0 }
|
disabled={selectedAccounts.size === 0}
|
||||||
>
|
>
|
||||||
{ t('next') }
|
{t('next')}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
@import 'choose-account/index';
|
@import 'choose-account/index';
|
||||||
|
@import 'redirect/index';
|
||||||
|
|
||||||
.permissions-connect {
|
.permissions-connect {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -1,16 +1,14 @@
|
|||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import React, { Component } from 'react'
|
import React, { Component } from 'react'
|
||||||
import { Switch, Route } from 'react-router-dom'
|
import { Switch, Route } from 'react-router-dom'
|
||||||
import ChooseAccount from './choose-account'
|
|
||||||
import { getEnvironmentType } from '../../../../app/scripts/lib/util'
|
import { getEnvironmentType } from '../../../../app/scripts/lib/util'
|
||||||
import {
|
import { ENVIRONMENT_TYPE_NOTIFICATION } from '../../../../app/scripts/lib/enums'
|
||||||
ENVIRONMENT_TYPE_FULLSCREEN,
|
import { DEFAULT_ROUTE } from '../../helpers/constants/routes'
|
||||||
ENVIRONMENT_TYPE_NOTIFICATION,
|
|
||||||
} from '../../../../app/scripts/lib/enums'
|
|
||||||
import {
|
|
||||||
DEFAULT_ROUTE,
|
|
||||||
} from '../../helpers/constants/routes'
|
|
||||||
import PermissionPageContainer from '../../components/app/permission-page-container'
|
import PermissionPageContainer from '../../components/app/permission-page-container'
|
||||||
|
import ChooseAccount from './choose-account'
|
||||||
|
import PermissionsRedirect from './redirect'
|
||||||
|
|
||||||
|
const APPROVE_TIMEOUT = 1200
|
||||||
|
|
||||||
export default class PermissionConnect extends Component {
|
export default class PermissionConnect extends Component {
|
||||||
static propTypes = {
|
static propTypes = {
|
||||||
@ -27,14 +25,12 @@ export default class PermissionConnect extends Component {
|
|||||||
addressLastConnectedMap: PropTypes.object.isRequired,
|
addressLastConnectedMap: PropTypes.object.isRequired,
|
||||||
lastConnectedInfo: PropTypes.object.isRequired,
|
lastConnectedInfo: PropTypes.object.isRequired,
|
||||||
permissionsRequestId: PropTypes.string,
|
permissionsRequestId: PropTypes.string,
|
||||||
|
hasPendingPermissionsRequests: PropTypes.bool.isRequired,
|
||||||
history: PropTypes.object.isRequired,
|
history: PropTypes.object.isRequired,
|
||||||
connectPath: PropTypes.string.isRequired,
|
connectPath: PropTypes.string.isRequired,
|
||||||
confirmPermissionPath: PropTypes.string.isRequired,
|
confirmPermissionPath: PropTypes.string.isRequired,
|
||||||
page: PropTypes.string.isRequired,
|
page: PropTypes.string.isRequired,
|
||||||
targetDomainMetadata: PropTypes.object,
|
targetDomainMetadata: PropTypes.object,
|
||||||
location: PropTypes.shape({
|
|
||||||
pathname: PropTypes.string,
|
|
||||||
}).isRequired,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static defaultProps = {
|
static defaultProps = {
|
||||||
@ -53,74 +49,27 @@ export default class PermissionConnect extends Component {
|
|||||||
selectedAccountAddresses: this.props.accounts.length === 1
|
selectedAccountAddresses: this.props.accounts.length === 1
|
||||||
? new Set([this.props.accounts[0].address])
|
? new Set([this.props.accounts[0].address])
|
||||||
: new Set(),
|
: new Set(),
|
||||||
permissionAccepted: null,
|
permissionsApproved: null,
|
||||||
origin: this.props.origin,
|
origin: this.props.origin,
|
||||||
|
targetDomainMetadata: this.props.targetDomainMetadata || {},
|
||||||
}
|
}
|
||||||
|
|
||||||
beforeUnload = () => {
|
beforeUnload = () => {
|
||||||
const { permissionsRequestId, rejectPermissionsRequest } = this.props
|
const { permissionsRequestId, rejectPermissionsRequest } = this.props
|
||||||
const { permissionAccepted } = this.state
|
const { permissionsApproved } = this.state
|
||||||
|
|
||||||
if (permissionAccepted === null && permissionsRequestId) {
|
if (permissionsApproved === null && permissionsRequestId) {
|
||||||
rejectPermissionsRequest(permissionsRequestId)
|
rejectPermissionsRequest(permissionsRequestId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
removeBeforeUnload = () => {
|
removeBeforeUnload = () => {
|
||||||
const environmentType = getEnvironmentType()
|
const environmentType = getEnvironmentType()
|
||||||
if (
|
if (environmentType === ENVIRONMENT_TYPE_NOTIFICATION) {
|
||||||
environmentType === ENVIRONMENT_TYPE_FULLSCREEN ||
|
|
||||||
environmentType === ENVIRONMENT_TYPE_NOTIFICATION
|
|
||||||
) {
|
|
||||||
window.removeEventListener('beforeunload', this.beforeUnload)
|
window.removeEventListener('beforeunload', this.beforeUnload)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate (prevProps) {
|
|
||||||
const { permissionsRequest, lastConnectedInfo } = this.props
|
|
||||||
const { redirecting, origin } = this.state
|
|
||||||
|
|
||||||
if (!permissionsRequest && prevProps.permissionsRequest && !redirecting) {
|
|
||||||
|
|
||||||
const accountsLastApprovedTime = lastConnectedInfo[origin]?.lastApproved || 0
|
|
||||||
const initialAccountsLastApprovedTime = prevProps.lastConnectedInfo[origin]?.lastApproved || 0
|
|
||||||
|
|
||||||
if (accountsLastApprovedTime > initialAccountsLastApprovedTime) {
|
|
||||||
this.redirectFlow(true)
|
|
||||||
} else {
|
|
||||||
this.redirectFlow(false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
selectAccounts = (addresses) => {
|
|
||||||
this.setState({
|
|
||||||
selectedAccountAddresses: addresses,
|
|
||||||
}, () => this.props.history.push(this.props.confirmPermissionPath))
|
|
||||||
}
|
|
||||||
|
|
||||||
redirectFlow (accepted) {
|
|
||||||
const { history, location, confirmPermissionPath } = this.props
|
|
||||||
|
|
||||||
this.setState({
|
|
||||||
redirecting: true,
|
|
||||||
permissionAccepted: accepted,
|
|
||||||
})
|
|
||||||
this.removeBeforeUnload()
|
|
||||||
|
|
||||||
if (getEnvironmentType() === ENVIRONMENT_TYPE_NOTIFICATION) {
|
|
||||||
setTimeout(async () => {
|
|
||||||
global.platform.closeCurrentWindow()
|
|
||||||
}, 1500)
|
|
||||||
} else if (location.pathname === confirmPermissionPath) {
|
|
||||||
setTimeout(async () => {
|
|
||||||
history.push(DEFAULT_ROUTE)
|
|
||||||
}, 1500)
|
|
||||||
} else {
|
|
||||||
history.push(DEFAULT_ROUTE)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount () {
|
componentDidMount () {
|
||||||
const {
|
const {
|
||||||
getCurrentWindowTab,
|
getCurrentWindowTab,
|
||||||
@ -136,26 +85,78 @@ export default class PermissionConnect extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const environmentType = getEnvironmentType()
|
const environmentType = getEnvironmentType()
|
||||||
if (
|
if (environmentType === ENVIRONMENT_TYPE_NOTIFICATION) {
|
||||||
environmentType === ENVIRONMENT_TYPE_FULLSCREEN ||
|
|
||||||
environmentType === ENVIRONMENT_TYPE_NOTIFICATION
|
|
||||||
) {
|
|
||||||
window.addEventListener('beforeunload', this.beforeUnload)
|
window.addEventListener('beforeunload', this.beforeUnload)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static getDerivedStateFromProps (props, state) {
|
||||||
|
const { permissionsRequest, targetDomainMetadata } = props
|
||||||
|
const { targetDomainMetadata: savedMetadata } = state
|
||||||
|
|
||||||
|
if (
|
||||||
|
permissionsRequest &&
|
||||||
|
savedMetadata.name !== targetDomainMetadata?.name
|
||||||
|
) {
|
||||||
|
return { targetDomainMetadata }
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidUpdate (prevProps) {
|
||||||
|
const { permissionsRequest, lastConnectedInfo } = this.props
|
||||||
|
const { redirecting, origin } = this.state
|
||||||
|
|
||||||
|
if (!permissionsRequest && prevProps.permissionsRequest && !redirecting) {
|
||||||
|
|
||||||
|
const accountsLastApprovedTime = lastConnectedInfo[origin]?.lastApproved || 0
|
||||||
|
const initialAccountsLastApprovedTime = prevProps.lastConnectedInfo[origin]?.lastApproved || 0
|
||||||
|
|
||||||
|
const approved = accountsLastApprovedTime > initialAccountsLastApprovedTime
|
||||||
|
this.redirect(approved)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
selectAccounts = (addresses) => {
|
||||||
|
this.setState({
|
||||||
|
selectedAccountAddresses: addresses,
|
||||||
|
}, () => this.props.history.push(this.props.confirmPermissionPath))
|
||||||
|
}
|
||||||
|
|
||||||
|
redirect (approved) {
|
||||||
|
this.setState({
|
||||||
|
redirecting: true,
|
||||||
|
permissionsApproved: approved,
|
||||||
|
})
|
||||||
|
this.removeBeforeUnload()
|
||||||
|
|
||||||
|
if (approved) {
|
||||||
|
setTimeout(this._doRedirect.bind(this), APPROVE_TIMEOUT)
|
||||||
|
} else {
|
||||||
|
this._doRedirect()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_doRedirect () {
|
||||||
|
const { history, hasPendingPermissionsRequests } = this.props
|
||||||
|
|
||||||
|
if (
|
||||||
|
!hasPendingPermissionsRequests &&
|
||||||
|
getEnvironmentType() === ENVIRONMENT_TYPE_NOTIFICATION
|
||||||
|
) {
|
||||||
|
global.platform.closeCurrentWindow()
|
||||||
|
} else {
|
||||||
|
history.push(DEFAULT_ROUTE)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
cancelPermissionsRequest = async (requestId) => {
|
cancelPermissionsRequest = async (requestId) => {
|
||||||
|
|
||||||
const { history, rejectPermissionsRequest } = this.props
|
const { rejectPermissionsRequest } = this.props
|
||||||
|
|
||||||
if (requestId) {
|
if (requestId) {
|
||||||
await rejectPermissionsRequest(requestId)
|
await rejectPermissionsRequest(requestId)
|
||||||
|
this.redirect(false)
|
||||||
if (getEnvironmentType() === ENVIRONMENT_TYPE_NOTIFICATION) {
|
|
||||||
window.close()
|
|
||||||
} else {
|
|
||||||
history.push(DEFAULT_ROUTE)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -193,7 +194,6 @@ export default class PermissionConnect extends Component {
|
|||||||
render () {
|
render () {
|
||||||
const {
|
const {
|
||||||
approvePermissionsRequest,
|
approvePermissionsRequest,
|
||||||
rejectPermissionsRequest,
|
|
||||||
accounts,
|
accounts,
|
||||||
showNewAccountModal,
|
showNewAccountModal,
|
||||||
newAccountNumber,
|
newAccountNumber,
|
||||||
@ -203,63 +203,68 @@ export default class PermissionConnect extends Component {
|
|||||||
permissionsRequestId,
|
permissionsRequestId,
|
||||||
connectPath,
|
connectPath,
|
||||||
confirmPermissionPath,
|
confirmPermissionPath,
|
||||||
targetDomainMetadata,
|
|
||||||
} = this.props
|
} = this.props
|
||||||
const {
|
const {
|
||||||
selectedAccountAddresses,
|
selectedAccountAddresses,
|
||||||
permissionAccepted,
|
permissionsApproved,
|
||||||
origin,
|
origin,
|
||||||
redirecting,
|
redirecting,
|
||||||
|
targetDomainMetadata,
|
||||||
} = this.state
|
} = this.state
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="permissions-connect">
|
<div className="permissions-connect">
|
||||||
{ this.renderTopBar() }
|
{ this.renderTopBar() }
|
||||||
<Switch>
|
{
|
||||||
<Route
|
redirecting && permissionsApproved
|
||||||
path={connectPath}
|
? (
|
||||||
exact
|
<PermissionsRedirect
|
||||||
render={() => (
|
domainMetadata={targetDomainMetadata}
|
||||||
<ChooseAccount
|
|
||||||
accounts={accounts}
|
|
||||||
nativeCurrency={nativeCurrency}
|
|
||||||
selectAccounts={(addresses) => this.selectAccounts(addresses)}
|
|
||||||
selectNewAccountViaModal={(handleAccountClick) => {
|
|
||||||
showNewAccountModal({
|
|
||||||
onCreateNewAccount: (address) => handleAccountClick(address),
|
|
||||||
newAccountNumber,
|
|
||||||
})
|
|
||||||
}}
|
|
||||||
addressLastConnectedMap={addressLastConnectedMap}
|
|
||||||
cancelPermissionsRequest={(requestId) => this.cancelPermissionsRequest(requestId)}
|
|
||||||
permissionsRequestId={permissionsRequestId}
|
|
||||||
selectedAccountAddresses={selectedAccountAddresses}
|
|
||||||
targetDomainMetadata={targetDomainMetadata}
|
|
||||||
/>
|
/>
|
||||||
)}
|
)
|
||||||
/>
|
: (
|
||||||
<Route
|
<Switch>
|
||||||
path={confirmPermissionPath}
|
<Route
|
||||||
exact
|
path={connectPath}
|
||||||
render={() => (
|
exact
|
||||||
<PermissionPageContainer
|
render={() => (
|
||||||
request={permissionsRequest || {}}
|
<ChooseAccount
|
||||||
approvePermissionsRequest={(request, accounts) => {
|
accounts={accounts}
|
||||||
approvePermissionsRequest(request, accounts)
|
nativeCurrency={nativeCurrency}
|
||||||
this.redirectFlow(true)
|
selectAccounts={(addresses) => this.selectAccounts(addresses)}
|
||||||
}}
|
selectNewAccountViaModal={(handleAccountClick) => {
|
||||||
rejectPermissionsRequest={(requestId) => {
|
showNewAccountModal({
|
||||||
rejectPermissionsRequest(requestId)
|
onCreateNewAccount: (address) => handleAccountClick(address),
|
||||||
this.redirectFlow(false)
|
newAccountNumber,
|
||||||
}}
|
})
|
||||||
selectedIdentities={accounts.filter((account) => selectedAccountAddresses.has(account.address))}
|
}}
|
||||||
redirect={redirecting}
|
addressLastConnectedMap={addressLastConnectedMap}
|
||||||
permissionRejected={ permissionAccepted === false }
|
cancelPermissionsRequest={(requestId) => this.cancelPermissionsRequest(requestId)}
|
||||||
cachedOrigin={origin}
|
permissionsRequestId={permissionsRequestId}
|
||||||
/>
|
selectedAccountAddresses={selectedAccountAddresses}
|
||||||
)}
|
targetDomainMetadata={targetDomainMetadata}
|
||||||
/>
|
/>
|
||||||
</Switch>
|
)}
|
||||||
|
/>
|
||||||
|
<Route
|
||||||
|
path={confirmPermissionPath}
|
||||||
|
exact
|
||||||
|
render={() => (
|
||||||
|
<PermissionPageContainer
|
||||||
|
request={permissionsRequest || {}}
|
||||||
|
approvePermissionsRequest={(request, accounts) => {
|
||||||
|
approvePermissionsRequest(request, accounts)
|
||||||
|
this.redirect(true)
|
||||||
|
}}
|
||||||
|
rejectPermissionsRequest={(requestId) => this.cancelPermissionsRequest(requestId)}
|
||||||
|
selectedIdentities={accounts.filter((account) => selectedAccountAddresses.has(account.address))}
|
||||||
|
cachedOrigin={origin}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</Switch>
|
||||||
|
)
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,10 @@ const mapStateToProps = (state, ownProps) => {
|
|||||||
const permissionsRequest = permissionsRequests
|
const permissionsRequest = permissionsRequests
|
||||||
.find((permissionsRequest) => permissionsRequest.metadata.id === permissionsRequestId)
|
.find((permissionsRequest) => permissionsRequest.metadata.id === permissionsRequestId)
|
||||||
|
|
||||||
|
const hasPendingPermissionsRequests = permissionsRequest
|
||||||
|
? permissionsRequests.length > 1
|
||||||
|
: permissionsRequests.length > 0
|
||||||
|
|
||||||
const { metadata = {} } = permissionsRequest || {}
|
const { metadata = {} } = permissionsRequest || {}
|
||||||
const { origin } = metadata
|
const { origin } = metadata
|
||||||
const nativeCurrency = getNativeCurrency(state)
|
const nativeCurrency = getNativeCurrency(state)
|
||||||
@ -62,6 +66,7 @@ const mapStateToProps = (state, ownProps) => {
|
|||||||
return {
|
return {
|
||||||
permissionsRequest,
|
permissionsRequest,
|
||||||
permissionsRequestId,
|
permissionsRequestId,
|
||||||
|
hasPendingPermissionsRequests,
|
||||||
accounts: accountsWithLabels,
|
accounts: accountsWithLabels,
|
||||||
origin,
|
origin,
|
||||||
newAccountNumber: accountsWithLabels.length + 1,
|
newAccountNumber: accountsWithLabels.length + 1,
|
||||||
|
1
ui/app/pages/permissions-connect/redirect/index.js
Normal file
1
ui/app/pages/permissions-connect/redirect/index.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
export { default } from './permissions-redirect.component'
|
82
ui/app/pages/permissions-connect/redirect/index.scss
Normal file
82
ui/app/pages/permissions-connect/redirect/index.scss
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
.permissions-redirect {
|
||||||
|
display: flex;
|
||||||
|
height: 100%;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
&__result {
|
||||||
|
@extend %header--24;
|
||||||
|
|
||||||
|
position: absolute;
|
||||||
|
top: 30%;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
text-align: center;
|
||||||
|
color: $Black-100;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__icons {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__center-icon {
|
||||||
|
display: flex;
|
||||||
|
position: relative;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__check {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
background: white url("/images/permissions-check.svg") no-repeat;
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__identicon, .icon-with-fallback__identicon {
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
|
||||||
|
&--default {
|
||||||
|
background-color: #777A87;
|
||||||
|
color: white;
|
||||||
|
width: 64px;
|
||||||
|
height: 64px;
|
||||||
|
border-radius: 32px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__identicon-container, .icon-with-fallback__identicon-container {
|
||||||
|
height: auto;
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
height: 64px;
|
||||||
|
width: 64px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__identicon-border, .icon-with-fallback__identicon-border {
|
||||||
|
height: 64px;
|
||||||
|
width: 64px;
|
||||||
|
border-radius: 50%;
|
||||||
|
border: 1px solid white;
|
||||||
|
background: #FFFFFF;
|
||||||
|
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.25);
|
||||||
|
}
|
||||||
|
|
||||||
|
&__identicon-border {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-with-fallback__identicon-border {
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
import React, { useContext } from 'react'
|
||||||
|
import PropTypes from 'prop-types'
|
||||||
|
import IconWithFallBack from '../../../components/ui/icon-with-fallback'
|
||||||
|
import { I18nContext } from '../../../contexts/i18n'
|
||||||
|
|
||||||
|
export default function PermissionsRedirect ({ domainMetadata }) {
|
||||||
|
|
||||||
|
const t = useContext(I18nContext)
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="permissions-redirect">
|
||||||
|
<div className="permissions-redirect__result">
|
||||||
|
{ t('connecting') }
|
||||||
|
<div className="permissions-redirect__icons">
|
||||||
|
<IconWithFallBack icon={domainMetadata.icon} name={domainMetadata.name} />
|
||||||
|
<div className="permissions-redirect__center-icon">
|
||||||
|
<span className="permissions-redirect__check" />
|
||||||
|
{ renderBrokenLine() }
|
||||||
|
</div>
|
||||||
|
<div className="permissions-redirect__identicon-container">
|
||||||
|
<div className="permissions-redirect__identicon-border">
|
||||||
|
<img src="/images/logo/metamask-fox.svg" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
|
function renderBrokenLine () {
|
||||||
|
return (
|
||||||
|
<svg width="131" height="2" viewBox="0 0 131 2" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M0 1H134" stroke="#CDD1E4" strokeLinejoin="round" strokeDasharray="8 7" />
|
||||||
|
</svg>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PermissionsRedirect.propTypes = {
|
||||||
|
domainMetadata: PropTypes.object.isRequired,
|
||||||
|
}
|
@ -173,17 +173,15 @@ export default class Routes extends Component {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
if (windowType === ENVIRONMENT_TYPE_POPUP) {
|
if (windowType === ENVIRONMENT_TYPE_POPUP && this.onConfirmPage()) {
|
||||||
return this.onConfirmPage() || hasPermissionsRequests
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
const isHandlingPermissionsRequest = Boolean(matchPath(location.pathname, {
|
const isHandlingPermissionsRequest = Boolean(matchPath(location.pathname, {
|
||||||
path: CONNECT_ROUTE, exact: false,
|
path: CONNECT_ROUTE, exact: false,
|
||||||
}))
|
})) || hasPermissionsRequests
|
||||||
|
|
||||||
if (hasPermissionsRequests || isHandlingPermissionsRequest) {
|
return isHandlingPermissionsRequest
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
|
@ -2056,9 +2056,11 @@ export function rejectPermissionsRequest (requestId) {
|
|||||||
background.rejectPermissionsRequest(requestId, (err) => {
|
background.rejectPermissionsRequest(requestId, (err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
dispatch(displayWarning(err.message))
|
dispatch(displayWarning(err.message))
|
||||||
reject()
|
return reject(err)
|
||||||
}
|
}
|
||||||
resolve()
|
return forceUpdateMetamaskState(dispatch)
|
||||||
|
.then(resolve)
|
||||||
|
.catch(reject)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user