mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-10-23 11:46:13 +02:00
1d2644423e
The 'copy-to-clipboard' icon was removed in #8190, and replaced with a new 'Copy' icon component. It was still being used in two places though, on the confirmation page for decryption and on the reveal seed phrase screen.. The new Copy icon is now used in these two places instead. It has been given a size of '17' to match the old icon size.
355 lines
10 KiB
JavaScript
355 lines
10 KiB
JavaScript
import React, { Component } from 'react'
|
|
import PropTypes from 'prop-types'
|
|
import copyToClipboard from 'copy-to-clipboard'
|
|
import classnames from 'classnames'
|
|
|
|
import AccountListItem from '../send/account-list-item/account-list-item.component'
|
|
import Button from '../../components/ui/button'
|
|
import Identicon from '../../components/ui/identicon'
|
|
import Tooltip from '../../components/ui/tooltip-v2'
|
|
import Copy from '../../components/ui/icon/copy-icon.component'
|
|
|
|
import { ENVIRONMENT_TYPE_NOTIFICATION } from '../../../../app/scripts/lib/enums'
|
|
import { getEnvironmentType } from '../../../../app/scripts/lib/util'
|
|
import { conversionUtil } from '../../helpers/utils/conversion-util'
|
|
|
|
export default class ConfirmDecryptMessage extends Component {
|
|
static contextTypes = {
|
|
t: PropTypes.func.isRequired,
|
|
metricsEvent: PropTypes.func.isRequired,
|
|
}
|
|
|
|
static propTypes = {
|
|
fromAccount: PropTypes.shape({
|
|
address: PropTypes.string.isRequired,
|
|
balance: PropTypes.string,
|
|
name: PropTypes.string,
|
|
}).isRequired,
|
|
clearConfirmTransaction: PropTypes.func.isRequired,
|
|
cancelDecryptMessage: PropTypes.func.isRequired,
|
|
decryptMessage: PropTypes.func.isRequired,
|
|
decryptMessageInline: PropTypes.func.isRequired,
|
|
conversionRate: PropTypes.number,
|
|
history: PropTypes.object.isRequired,
|
|
mostRecentOverviewPage: PropTypes.string.isRequired,
|
|
requesterAddress: PropTypes.string,
|
|
txData: PropTypes.object,
|
|
domainMetadata: PropTypes.object,
|
|
}
|
|
|
|
state = {
|
|
fromAccount: this.props.fromAccount,
|
|
copyToClipboardPressed: false,
|
|
hasCopied: false,
|
|
}
|
|
|
|
componentDidMount = () => {
|
|
if (getEnvironmentType(window.location.href) === ENVIRONMENT_TYPE_NOTIFICATION) {
|
|
window.addEventListener('beforeunload', this._beforeUnload)
|
|
}
|
|
}
|
|
|
|
componentWillUnmount = () => {
|
|
this._removeBeforeUnload()
|
|
}
|
|
|
|
_beforeUnload = async (event) => {
|
|
const {
|
|
clearConfirmTransaction,
|
|
cancelDecryptMessage,
|
|
txData,
|
|
} = this.props
|
|
const { metricsEvent } = this.context
|
|
await cancelDecryptMessage(txData, event)
|
|
metricsEvent({
|
|
eventOpts: {
|
|
category: 'Messages',
|
|
action: 'Decrypt Message Request',
|
|
name: 'Cancel Via Notification Close',
|
|
},
|
|
})
|
|
clearConfirmTransaction()
|
|
}
|
|
|
|
_removeBeforeUnload = () => {
|
|
if (getEnvironmentType(window.location.href) === ENVIRONMENT_TYPE_NOTIFICATION) {
|
|
window.removeEventListener('beforeunload', this._beforeUnload)
|
|
}
|
|
}
|
|
|
|
copyMessage = () => {
|
|
copyToClipboard(this.state.rawMessage)
|
|
this.context.metricsEvent({
|
|
eventOpts: {
|
|
category: 'Messages',
|
|
action: 'Decrypt Message Copy',
|
|
name: 'Copy',
|
|
},
|
|
})
|
|
this.setState({ hasCopied: true })
|
|
setTimeout(() => this.setState({ hasCopied: false }), 3000)
|
|
}
|
|
|
|
renderHeader = () => {
|
|
return (
|
|
<div className="request-decrypt-message__header">
|
|
<div className="request-decrypt-message__header-background" />
|
|
|
|
<div className="request-decrypt-message__header__text">
|
|
{ this.context.t('decryptRequest') }
|
|
</div>
|
|
|
|
<div className="request-decrypt-message__header__tip-container">
|
|
<div className="request-decrypt-message__header__tip" />
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
renderAccount = () => {
|
|
const { fromAccount } = this.state
|
|
const { t } = this.context
|
|
|
|
return (
|
|
<div className="request-decrypt-message__account">
|
|
<div className="request-decrypt-message__account-text">
|
|
{ `${t('account')}:` }
|
|
</div>
|
|
|
|
<div className="request-decrypt-message__account-item">
|
|
<AccountListItem
|
|
account={fromAccount}
|
|
displayBalance={false}
|
|
/>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
renderBalance = () => {
|
|
const { conversionRate } = this.props
|
|
const { fromAccount: { balance } } = this.state
|
|
const { t } = this.context
|
|
|
|
const balanceInEther = conversionUtil(balance, {
|
|
fromNumericBase: 'hex',
|
|
toNumericBase: 'dec',
|
|
fromDenomination: 'WEI',
|
|
numberOfDecimals: 6,
|
|
conversionRate,
|
|
})
|
|
|
|
return (
|
|
<div className="request-decrypt-message__balance">
|
|
<div className="request-decrypt-message__balance-text">
|
|
{ `${t('balance')}:` }
|
|
</div>
|
|
<div className="request-decrypt-message__balance-value">
|
|
{ `${balanceInEther} ETH` }
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
renderRequestIcon = () => {
|
|
const { requesterAddress } = this.props
|
|
|
|
return (
|
|
<div className="request-decrypt-message__request-icon">
|
|
<Identicon
|
|
diameter={40}
|
|
address={requesterAddress}
|
|
/>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
renderAccountInfo = () => {
|
|
return (
|
|
<div className="request-decrypt-message__account-info">
|
|
{ this.renderAccount() }
|
|
{ this.renderRequestIcon() }
|
|
{ this.renderBalance() }
|
|
</div>
|
|
)
|
|
}
|
|
|
|
renderBody = () => {
|
|
const { decryptMessageInline, domainMetadata, txData } = this.props
|
|
const { t } = this.context
|
|
|
|
const origin = domainMetadata[txData.msgParams.origin]
|
|
const notice = t('decryptMessageNotice', [origin.name])
|
|
|
|
const {
|
|
hasCopied,
|
|
hasDecrypted,
|
|
hasError,
|
|
rawMessage,
|
|
errorMessage,
|
|
copyToClipboardPressed,
|
|
} = this.state
|
|
|
|
return (
|
|
<div className="request-decrypt-message__body">
|
|
{ this.renderAccountInfo() }
|
|
<div
|
|
className="request-decrypt-message__visual"
|
|
>
|
|
<section>
|
|
{origin.icon ? (
|
|
<img
|
|
className="request-decrypt-message__visual-identicon"
|
|
src={origin.icon}
|
|
/>
|
|
) : (
|
|
<i className="request-decrypt-message__visual-identicon--default">
|
|
{origin.name.charAt(0).toUpperCase()}
|
|
</i>
|
|
)}
|
|
<div
|
|
className="request-decrypt-message__notice"
|
|
>
|
|
{ notice }
|
|
</div>
|
|
</section>
|
|
</div>
|
|
<div
|
|
className="request-decrypt-message__message"
|
|
>
|
|
<div
|
|
className="request-decrypt-message__message-text"
|
|
>
|
|
{ !hasDecrypted && !hasError ? txData.msgParams.data : rawMessage }
|
|
{ !hasError ? '' : errorMessage }
|
|
</div>
|
|
<div
|
|
className={classnames({
|
|
'request-decrypt-message__message-cover': true,
|
|
'request-decrypt-message__message-lock--pressed': hasDecrypted || hasError,
|
|
})}
|
|
>
|
|
</div>
|
|
<div
|
|
className={classnames({
|
|
'request-decrypt-message__message-lock': true,
|
|
'request-decrypt-message__message-lock--pressed': hasDecrypted || hasError,
|
|
})}
|
|
onClick={(event) => {
|
|
decryptMessageInline(txData, event).then((result) => {
|
|
if (!result.error) {
|
|
this.setState({ hasDecrypted: true, rawMessage: result.rawData })
|
|
} else {
|
|
this.setState({ hasError: true, errorMessage: this.context.t('decryptInlineError', [result.error]) })
|
|
}
|
|
})
|
|
}}
|
|
>
|
|
<img src="images/lock.svg" />
|
|
<div
|
|
className="request-decrypt-message__message-lock-text"
|
|
>
|
|
{t('decryptMetamask')}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{ hasDecrypted ?
|
|
(
|
|
<div
|
|
className={classnames({
|
|
'request-decrypt-message__message-copy': true,
|
|
'request-decrypt-message__message-copy--pressed': copyToClipboardPressed,
|
|
})}
|
|
onClick={() => this.copyMessage()}
|
|
onMouseDown={() => this.setState({ copyToClipboardPressed: true })}
|
|
onMouseUp={() => this.setState({ copyToClipboardPressed: false })}
|
|
>
|
|
<Tooltip
|
|
position="bottom"
|
|
title={hasCopied ? t('copiedExclamation') : t('copyToClipboard')}
|
|
wrapperClassName="request-decrypt-message__message-copy-tooltip"
|
|
>
|
|
<div
|
|
className="request-decrypt-message__message-copy-text"
|
|
>
|
|
{t('decryptCopy')}
|
|
</div>
|
|
<Copy size={17} color="#3098DC" />
|
|
</Tooltip>
|
|
</div>
|
|
)
|
|
:
|
|
<div></div>
|
|
}
|
|
</div>
|
|
)
|
|
}
|
|
|
|
renderFooter = () => {
|
|
const {
|
|
cancelDecryptMessage,
|
|
clearConfirmTransaction,
|
|
decryptMessage,
|
|
history,
|
|
mostRecentOverviewPage,
|
|
txData,
|
|
} = this.props
|
|
const { metricsEvent, t } = this.context
|
|
|
|
return (
|
|
<div className="request-decrypt-message__footer">
|
|
<Button
|
|
type="default"
|
|
large
|
|
className="request-decrypt-message__footer__cancel-button"
|
|
onClick={async (event) => {
|
|
this._removeBeforeUnload()
|
|
await cancelDecryptMessage(txData, event)
|
|
metricsEvent({
|
|
eventOpts: {
|
|
category: 'Messages',
|
|
action: 'Decrypt Message Request',
|
|
name: 'Cancel',
|
|
},
|
|
})
|
|
clearConfirmTransaction()
|
|
history.push(mostRecentOverviewPage)
|
|
}}
|
|
>
|
|
{ t('cancel') }
|
|
</Button>
|
|
<Button
|
|
type="secondary"
|
|
large
|
|
className="request-decrypt-message__footer__sign-button"
|
|
onClick={async (event) => {
|
|
this._removeBeforeUnload()
|
|
await decryptMessage(txData, event)
|
|
metricsEvent({
|
|
eventOpts: {
|
|
category: 'Messages',
|
|
action: 'Decrypt Message Request',
|
|
name: 'Confirm',
|
|
},
|
|
})
|
|
clearConfirmTransaction()
|
|
history.push(mostRecentOverviewPage)
|
|
}}
|
|
>
|
|
{ t('decrypt') }
|
|
</Button>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
render = () => {
|
|
return (
|
|
<div className="request-decrypt-message__container">
|
|
{ this.renderHeader() }
|
|
{ this.renderBody() }
|
|
{ this.renderFooter() }
|
|
</div>
|
|
)
|
|
}
|
|
}
|