mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-24 11:01:41 +01:00
b97cd1dc04
The notification window is now kept open after the connect flow if there are still pending confirmations. Previously, the notification window would be closed after the connect flow no matter what, and any pending confirmations would never be shown to the user. This was accomplished by redirecting to the home screen after the connect flow. The logic for deciding whether or not to close the window is already handled by the home page. This does have the unfortunate side-effect of briefly rendering the home page before the window closes, but this is a minor problem that exists already in a number of other scenarios, and it will be fixed in a subsequent PR. Fixes #8973
263 lines
8.0 KiB
JavaScript
263 lines
8.0 KiB
JavaScript
import PropTypes from 'prop-types'
|
|
import React, { Component } from 'react'
|
|
import { Switch, Route } from 'react-router-dom'
|
|
import { getEnvironmentType } from '../../../../app/scripts/lib/util'
|
|
import { ENVIRONMENT_TYPE_NOTIFICATION } from '../../../../app/scripts/lib/enums'
|
|
import { DEFAULT_ROUTE } from '../../helpers/constants/routes'
|
|
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 {
|
|
static propTypes = {
|
|
approvePermissionsRequest: PropTypes.func.isRequired,
|
|
rejectPermissionsRequest: PropTypes.func.isRequired,
|
|
getRequestAccountTabIds: PropTypes.func.isRequired,
|
|
getCurrentWindowTab: PropTypes.func.isRequired,
|
|
accounts: PropTypes.array.isRequired,
|
|
currentAddress: PropTypes.string.isRequired,
|
|
origin: PropTypes.string,
|
|
showNewAccountModal: PropTypes.func.isRequired,
|
|
newAccountNumber: PropTypes.number.isRequired,
|
|
nativeCurrency: PropTypes.string,
|
|
permissionsRequest: PropTypes.object,
|
|
addressLastConnectedMap: PropTypes.object.isRequired,
|
|
lastConnectedInfo: PropTypes.object.isRequired,
|
|
permissionsRequestId: PropTypes.string,
|
|
history: PropTypes.object.isRequired,
|
|
connectPath: PropTypes.string.isRequired,
|
|
confirmPermissionPath: PropTypes.string.isRequired,
|
|
page: PropTypes.string.isRequired,
|
|
targetDomainMetadata: PropTypes.shape({
|
|
extensionId: PropTypes.string,
|
|
icon: PropTypes.string,
|
|
host: PropTypes.string.isRequired,
|
|
name: PropTypes.string.isRequired,
|
|
origin: PropTypes.string.isRequired,
|
|
}),
|
|
}
|
|
|
|
static defaultProps = {
|
|
origin: '',
|
|
nativeCurrency: '',
|
|
permissionsRequest: undefined,
|
|
permissionsRequestId: '',
|
|
}
|
|
|
|
static contextTypes = {
|
|
t: PropTypes.func,
|
|
}
|
|
|
|
state = {
|
|
redirecting: false,
|
|
selectedAccountAddresses: new Set([this.props.currentAddress]),
|
|
permissionsApproved: null,
|
|
origin: this.props.origin,
|
|
targetDomainMetadata: this.props.targetDomainMetadata || {},
|
|
}
|
|
|
|
beforeUnload = () => {
|
|
const { permissionsRequestId, rejectPermissionsRequest } = this.props
|
|
const { permissionsApproved } = this.state
|
|
|
|
if (permissionsApproved === null && permissionsRequestId) {
|
|
rejectPermissionsRequest(permissionsRequestId)
|
|
}
|
|
}
|
|
|
|
removeBeforeUnload = () => {
|
|
const environmentType = getEnvironmentType()
|
|
if (environmentType === ENVIRONMENT_TYPE_NOTIFICATION) {
|
|
window.removeEventListener('beforeunload', this.beforeUnload)
|
|
}
|
|
}
|
|
|
|
componentDidMount () {
|
|
const {
|
|
getCurrentWindowTab,
|
|
getRequestAccountTabIds,
|
|
permissionsRequest,
|
|
history,
|
|
} = this.props
|
|
getCurrentWindowTab()
|
|
getRequestAccountTabIds()
|
|
|
|
if (!permissionsRequest) {
|
|
return history.push(DEFAULT_ROUTE)
|
|
}
|
|
|
|
const environmentType = getEnvironmentType()
|
|
if (environmentType === ENVIRONMENT_TYPE_NOTIFICATION) {
|
|
window.addEventListener('beforeunload', this.beforeUnload)
|
|
}
|
|
}
|
|
|
|
static getDerivedStateFromProps (props, state) {
|
|
const { permissionsRequest, targetDomainMetadata } = props
|
|
const { targetDomainMetadata: savedMetadata } = state
|
|
|
|
if (
|
|
permissionsRequest &&
|
|
savedMetadata.origin !== targetDomainMetadata?.origin
|
|
) {
|
|
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) {
|
|
const { history } = this.props
|
|
this.setState({
|
|
redirecting: true,
|
|
permissionsApproved: approved,
|
|
})
|
|
this.removeBeforeUnload()
|
|
|
|
if (approved) {
|
|
setTimeout(() => history.push(DEFAULT_ROUTE), APPROVE_TIMEOUT)
|
|
} else {
|
|
history.push(DEFAULT_ROUTE)
|
|
}
|
|
}
|
|
|
|
cancelPermissionsRequest = async (requestId) => {
|
|
|
|
const { rejectPermissionsRequest } = this.props
|
|
|
|
if (requestId) {
|
|
await rejectPermissionsRequest(requestId)
|
|
this.redirect(false)
|
|
}
|
|
}
|
|
|
|
goBack () {
|
|
const { history, connectPath } = this.props
|
|
history.push(connectPath)
|
|
}
|
|
|
|
renderTopBar () {
|
|
const { redirecting } = this.state
|
|
const { page } = this.props
|
|
const { t } = this.context
|
|
return !redirecting
|
|
? (
|
|
<div
|
|
className="permissions-connect__top-bar"
|
|
>
|
|
{ page === '2'
|
|
? (
|
|
<div className="permissions-connect__back" onClick={() => this.goBack()}>
|
|
<i className="fas fa-chevron-left" />
|
|
{ t('back') }
|
|
</div>
|
|
)
|
|
: null
|
|
}
|
|
<div className="permissions-connect__page-count">
|
|
{ t('xOfY', [ page, '2' ]) }
|
|
</div>
|
|
</div>
|
|
)
|
|
: null
|
|
}
|
|
|
|
render () {
|
|
const {
|
|
approvePermissionsRequest,
|
|
accounts,
|
|
showNewAccountModal,
|
|
newAccountNumber,
|
|
nativeCurrency,
|
|
permissionsRequest,
|
|
addressLastConnectedMap,
|
|
permissionsRequestId,
|
|
connectPath,
|
|
confirmPermissionPath,
|
|
} = this.props
|
|
const {
|
|
selectedAccountAddresses,
|
|
permissionsApproved,
|
|
redirecting,
|
|
targetDomainMetadata,
|
|
} = this.state
|
|
|
|
return (
|
|
<div className="permissions-connect">
|
|
{ this.renderTopBar() }
|
|
{
|
|
redirecting && permissionsApproved
|
|
? (
|
|
<PermissionsRedirect
|
|
domainMetadata={targetDomainMetadata}
|
|
/>
|
|
)
|
|
: (
|
|
<Switch>
|
|
<Route
|
|
path={connectPath}
|
|
exact
|
|
render={() => (
|
|
<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
|
|
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))}
|
|
targetDomainMetadata={targetDomainMetadata}
|
|
/>
|
|
)}
|
|
/>
|
|
</Switch>
|
|
)
|
|
}
|
|
</div>
|
|
)
|
|
}
|
|
}
|