mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
parent
b378e57b27
commit
1747f91bf1
@ -1,52 +1,47 @@
|
||||
import React, { Component } from 'react'
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import copyToClipboard from 'copy-to-clipboard'
|
||||
import { exportAsFile } from '../../../helpers/utils/util'
|
||||
import Copy from '../icon/copy-icon.component'
|
||||
import { useI18nContext } from '../../../hooks/useI18nContext'
|
||||
import { useCopyToClipboard } from '../../../hooks/useCopyToClipboard'
|
||||
|
||||
class ExportTextContainer extends Component {
|
||||
render () {
|
||||
const { text = '' } = this.props
|
||||
const { t } = this.context
|
||||
function ExportTextContainer ({ text = '' }) {
|
||||
const t = useI18nContext()
|
||||
const [copied, handleCopy] = useCopyToClipboard()
|
||||
|
||||
return (
|
||||
<div className="export-text-container">
|
||||
<div className="export-text-container__text-container">
|
||||
<div className="export-text-container__text notranslate">
|
||||
{text}
|
||||
return (
|
||||
<div className="export-text-container">
|
||||
<div className="export-text-container__text-container">
|
||||
<div className="export-text-container__text notranslate">{text}</div>
|
||||
</div>
|
||||
<div className="export-text-container__buttons-container">
|
||||
<div
|
||||
className="export-text-container__button export-text-container__button--copy"
|
||||
onClick={() => {
|
||||
handleCopy(text)
|
||||
}}
|
||||
>
|
||||
<Copy size={17} color="#3098DC" />
|
||||
<div className="export-text-container__button-text">
|
||||
{copied ? t('copiedExclamation') : t('copyToClipboard')}
|
||||
</div>
|
||||
</div>
|
||||
<div className="export-text-container__buttons-container">
|
||||
<div
|
||||
className="export-text-container__button export-text-container__button--copy"
|
||||
onClick={() => copyToClipboard(text)}
|
||||
>
|
||||
<Copy size={17} color="#3098DC" />
|
||||
<div className="export-text-container__button-text">
|
||||
{t('copyToClipboard')}
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="export-text-container__button"
|
||||
onClick={() => exportAsFile('', text)}
|
||||
>
|
||||
<img src="images/download.svg" alt="" />
|
||||
<div className="export-text-container__button-text">
|
||||
{t('saveAsCsvFile')}
|
||||
</div>
|
||||
<div
|
||||
className="export-text-container__button"
|
||||
onClick={() => exportAsFile('', text)}
|
||||
>
|
||||
<img src="images/download.svg" alt="" />
|
||||
<div className="export-text-container__button-text">
|
||||
{t('saveAsCsvFile')}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
ExportTextContainer.propTypes = {
|
||||
text: PropTypes.string,
|
||||
}
|
||||
|
||||
ExportTextContainer.contextTypes = {
|
||||
t: PropTypes.func,
|
||||
}
|
||||
|
||||
export default ExportTextContainer
|
||||
export default React.memo(ExportTextContainer)
|
||||
|
28
ui/app/hooks/useCopyToClipboard.js
Normal file
28
ui/app/hooks/useCopyToClipboard.js
Normal file
@ -0,0 +1,28 @@
|
||||
import { useState, useCallback } from 'react'
|
||||
import copyToClipboard from 'copy-to-clipboard'
|
||||
import { useTimeout } from './useTimeout'
|
||||
|
||||
/**
|
||||
* useCopyToClipboard
|
||||
*
|
||||
* @param {number} [delay=3000] - delay in ms
|
||||
*
|
||||
* @return {[boolean, Function]}
|
||||
*/
|
||||
const DEFAULT_DELAY = 3000
|
||||
|
||||
export function useCopyToClipboard (delay = DEFAULT_DELAY) {
|
||||
const [copied, setCopied] = useState(false)
|
||||
const startTimeout = useTimeout(() => setCopied(false), delay, false)
|
||||
|
||||
const handleCopy = useCallback(
|
||||
(text) => {
|
||||
setCopied(true)
|
||||
startTimeout()
|
||||
copyToClipboard(text)
|
||||
},
|
||||
[startTimeout],
|
||||
)
|
||||
|
||||
return [copied, handleCopy]
|
||||
}
|
46
ui/app/hooks/useTimeout.js
Normal file
46
ui/app/hooks/useTimeout.js
Normal file
@ -0,0 +1,46 @@
|
||||
import { useState, useEffect, useRef, useCallback } from 'react'
|
||||
|
||||
/**
|
||||
* useTimeout
|
||||
*
|
||||
* @param {Function} cb - callback function inside setTimeout
|
||||
* @param {number} delay - delay in ms
|
||||
* @param {boolean} [immediate] - determines whether the timeout is invoked immediately
|
||||
*
|
||||
* @return {Function}
|
||||
*/
|
||||
export function useTimeout (cb, delay, immediate = true) {
|
||||
const saveCb = useRef()
|
||||
const [timeoutId, setTimeoutId] = useState(null)
|
||||
|
||||
useEffect(() => {
|
||||
saveCb.current = cb
|
||||
}, [cb])
|
||||
|
||||
useEffect(() => {
|
||||
if (timeoutId !== 'start') {
|
||||
return
|
||||
}
|
||||
|
||||
const id = setTimeout(() => {
|
||||
saveCb.current()
|
||||
}, delay)
|
||||
|
||||
setTimeoutId(id)
|
||||
|
||||
return () => {
|
||||
clearTimeout(timeoutId)
|
||||
}
|
||||
}, [delay, timeoutId])
|
||||
|
||||
const startTimeout = useCallback(() => {
|
||||
clearTimeout(timeoutId)
|
||||
setTimeoutId('start')
|
||||
}, [timeoutId])
|
||||
|
||||
if (immediate) {
|
||||
startTimeout()
|
||||
}
|
||||
|
||||
return startTimeout
|
||||
}
|
@ -106,7 +106,8 @@
|
||||
height: 20px;
|
||||
padding: 0;
|
||||
background: none;
|
||||
padding-left: 10px;
|
||||
padding-left: 0;
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,85 +1,102 @@
|
||||
import React, { PureComponent } from 'react'
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { Redirect } from 'react-router-dom'
|
||||
|
||||
import Identicon from '../../../../components/ui/identicon'
|
||||
import Copy from '../../../../components/ui/icon/copy-icon.component'
|
||||
import Button from '../../../../components/ui/button/button.component'
|
||||
import copyToClipboard from 'copy-to-clipboard'
|
||||
|
||||
import Tooltip from '../../../../components/ui/tooltip-v2'
|
||||
import { useI18nContext } from '../../../../hooks/useI18nContext'
|
||||
import { useCopyToClipboard } from '../../../../hooks/useCopyToClipboard'
|
||||
|
||||
function quadSplit (address) {
|
||||
return '0x ' + address.slice(2).match(/.{1,4}/g).join(' ')
|
||||
return (
|
||||
'0x ' +
|
||||
address
|
||||
.slice(2)
|
||||
.match(/.{1,4}/g)
|
||||
.join(' ')
|
||||
)
|
||||
}
|
||||
|
||||
export default class ViewContact extends PureComponent {
|
||||
function ViewContact ({
|
||||
history,
|
||||
name,
|
||||
address,
|
||||
checkSummedAddress,
|
||||
memo,
|
||||
editRoute,
|
||||
listRoute,
|
||||
}) {
|
||||
const t = useI18nContext()
|
||||
const [copied, handleCopy] = useCopyToClipboard()
|
||||
|
||||
static contextTypes = {
|
||||
t: PropTypes.func,
|
||||
if (!address) {
|
||||
return <Redirect to={{ pathname: listRoute }} />
|
||||
}
|
||||
|
||||
static propTypes = {
|
||||
name: PropTypes.string,
|
||||
address: PropTypes.string,
|
||||
history: PropTypes.object,
|
||||
checkSummedAddress: PropTypes.string,
|
||||
memo: PropTypes.string,
|
||||
editRoute: PropTypes.string,
|
||||
listRoute: PropTypes.string.isRequired,
|
||||
}
|
||||
|
||||
render () {
|
||||
const { t } = this.context
|
||||
const { history, name, address, checkSummedAddress, memo, editRoute, listRoute } = this.props
|
||||
|
||||
if (!address) {
|
||||
return <Redirect to={{ pathname: listRoute }} />
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="settings-page__content-row">
|
||||
<div className="settings-page__content-item">
|
||||
<div className="settings-page__header address-book__header">
|
||||
<Identicon address={address} diameter={60} />
|
||||
<div className="address-book__header__name">{ name }</div>
|
||||
return (
|
||||
<div className="settings-page__content-row">
|
||||
<div className="settings-page__content-item">
|
||||
<div className="settings-page__header address-book__header">
|
||||
<Identicon address={address} diameter={60} />
|
||||
<div className="address-book__header__name">{name}</div>
|
||||
</div>
|
||||
<div className="address-book__view-contact__group">
|
||||
<Button
|
||||
type="secondary"
|
||||
onClick={() => {
|
||||
history.push(`${editRoute}/${address}`)
|
||||
}}
|
||||
>
|
||||
{t('edit')}
|
||||
</Button>
|
||||
</div>
|
||||
<div className="address-book__view-contact__group">
|
||||
<div className="address-book__view-contact__group__label">
|
||||
{t('ethereumPublicAddress')}
|
||||
</div>
|
||||
<div className="address-book__view-contact__group">
|
||||
<Button
|
||||
type="secondary"
|
||||
onClick={() => {
|
||||
history.push(`${editRoute}/${address}`)
|
||||
}}
|
||||
>
|
||||
{t('edit')}
|
||||
</Button>
|
||||
</div>
|
||||
<div className="address-book__view-contact__group">
|
||||
<div className="address-book__view-contact__group__label">
|
||||
{ t('ethereumPublicAddress') }
|
||||
<div className="address-book__view-contact__group__value">
|
||||
<div className="address-book__view-contact__group__static-address">
|
||||
{quadSplit(checkSummedAddress)}
|
||||
</div>
|
||||
<div className="address-book__view-contact__group__value">
|
||||
<div
|
||||
className="address-book__view-contact__group__static-address"
|
||||
>
|
||||
{ quadSplit(checkSummedAddress) }
|
||||
</div>
|
||||
<Tooltip
|
||||
position="bottom"
|
||||
title={copied ? t('copiedExclamation') : t('copyToClipboard')}
|
||||
>
|
||||
<button
|
||||
className="address-book__view-contact__group__static-address--copy-icon"
|
||||
onClick={() => copyToClipboard(checkSummedAddress)}
|
||||
onClick={() => {
|
||||
handleCopy(checkSummedAddress)
|
||||
}}
|
||||
>
|
||||
<Copy size={20} color="#3098DC" />
|
||||
</button>
|
||||
</div>
|
||||
</Tooltip>
|
||||
</div>
|
||||
<div className="address-book__view-contact__group">
|
||||
<div className="address-book__view-contact__group__label--capitalized">
|
||||
{ t('memo') }
|
||||
</div>
|
||||
<div className="address-book__view-contact__group__static-address">
|
||||
{ memo }
|
||||
</div>
|
||||
</div>
|
||||
<div className="address-book__view-contact__group">
|
||||
<div className="address-book__view-contact__group__label--capitalized">
|
||||
{t('memo')}
|
||||
</div>
|
||||
<div className="address-book__view-contact__group__static-address">
|
||||
{memo}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
ViewContact.propTypes = {
|
||||
name: PropTypes.string,
|
||||
address: PropTypes.string,
|
||||
history: PropTypes.object,
|
||||
checkSummedAddress: PropTypes.string,
|
||||
memo: PropTypes.string,
|
||||
editRoute: PropTypes.string,
|
||||
listRoute: PropTypes.string.isRequired,
|
||||
}
|
||||
|
||||
export default React.memo(ViewContact)
|
||||
|
Loading…
x
Reference in New Issue
Block a user