Merge pull request #3420 from ethcore/refactor-copy-to-clipboard
refactor copy to clipboard functionality
This commit is contained in:
		
						commit
						1418c3175a
					
				
							
								
								
									
										24
									
								
								js/src/ui/CopyToClipboard/copyToClipboard.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								js/src/ui/CopyToClipboard/copyToClipboard.css
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,24 @@ | ||||
| /* Copyright 2015, 2016 Ethcore (UK) Ltd. | ||||
| /* This file is part of Parity. | ||||
| /* | ||||
| /* Parity is free software: you can redistribute it and/or modify | ||||
| /* it under the terms of the GNU General Public License as published by | ||||
| /* the Free Software Foundation, either version 3 of the License, or | ||||
| /* (at your option) any later version. | ||||
| /* | ||||
| /* Parity is distributed in the hope that it will be useful, | ||||
| /* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| /* GNU General Public License for more details. | ||||
| /* | ||||
| /* You should have received a copy of the GNU General Public License | ||||
| /* along with Parity.  If not, see <http://www.gnu.org/licenses/>. | ||||
| */ | ||||
| 
 | ||||
| .wrapper { | ||||
|   display: inline-block; | ||||
| } | ||||
| 
 | ||||
| .data { | ||||
|   font-family: monospace; | ||||
| } | ||||
| @ -16,15 +16,18 @@ | ||||
| 
 | ||||
| import React, { Component, PropTypes } from 'react'; | ||||
| import { IconButton } from 'material-ui'; | ||||
| import Snackbar from 'material-ui/Snackbar'; | ||||
| import Clipboard from 'react-copy-to-clipboard'; | ||||
| import CopyIcon from 'material-ui/svg-icons/content/content-copy'; | ||||
| import Theme from '../Theme'; | ||||
| import { darkBlack } from 'material-ui/styles/colors'; | ||||
| const { textColor, disabledTextColor } = Theme.flatButton; | ||||
| 
 | ||||
| import styles from './copyToClipboard.css'; | ||||
| 
 | ||||
| export default class CopyToClipboard extends Component { | ||||
|   static propTypes = { | ||||
|     data: PropTypes.string.isRequired, | ||||
|     label: PropTypes.string, | ||||
|     onCopy: PropTypes.func, | ||||
|     size: PropTypes.number, // in px
 | ||||
|     cooldown: PropTypes.number // in ms
 | ||||
| @ -32,32 +35,46 @@ export default class CopyToClipboard extends Component { | ||||
| 
 | ||||
|   static defaultProps = { | ||||
|     className: '', | ||||
|     label: 'copy to clipboard', | ||||
|     onCopy: () => {}, | ||||
|     size: 16, | ||||
|     cooldown: 1000 | ||||
|   }; | ||||
| 
 | ||||
|   state = { | ||||
|     copied: false | ||||
|     copied: false, | ||||
|     timeout: null | ||||
|   }; | ||||
| 
 | ||||
|   componentWillUnmount () { | ||||
|     const { timeoutId } = this.state; | ||||
|     if (timeoutId) { | ||||
|       window.clearTimeout(timeoutId); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   render () { | ||||
|     const { data, label, size } = this.props; | ||||
|     const { data, size } = this.props; | ||||
|     const { copied } = this.state; | ||||
| 
 | ||||
|     return ( | ||||
|       <Clipboard onCopy={ this.onCopy } text={ data }> | ||||
|         <IconButton | ||||
|           tooltip={ copied ? 'done!' : label } | ||||
|           disableTouchRipple | ||||
|           tooltipPosition={ 'top-right' } | ||||
|           tooltipStyles={ { marginTop: `-${size / 4}px` } } | ||||
|           style={ { width: size, height: size, padding: '0' } } | ||||
|           iconStyle={ { width: size, height: size } } | ||||
|         > | ||||
|           <CopyIcon color={ copied ? disabledTextColor : textColor } /> | ||||
|         </IconButton> | ||||
|         <div className={ styles.wrapper }> | ||||
|           <Snackbar | ||||
|             open={ copied } | ||||
|             message={ | ||||
|               <div>copied <code className={ styles.data }>{ data }</code> to clipboard</div> | ||||
|             } | ||||
|             autoHideDuration={ 2000 } | ||||
|             bodyStyle={ { backgroundColor: darkBlack } } | ||||
|           /> | ||||
|           <IconButton | ||||
|             disableTouchRipple | ||||
|             style={ { width: size, height: size, padding: '0' } } | ||||
|             iconStyle={ { width: size, height: size } } | ||||
|           > | ||||
|             <CopyIcon color={ copied ? disabledTextColor : textColor } /> | ||||
|           </IconButton> | ||||
|         </div> | ||||
|       </Clipboard> | ||||
|     ); | ||||
|   } | ||||
| @ -65,11 +82,12 @@ export default class CopyToClipboard extends Component { | ||||
|   onCopy = () => { | ||||
|     const { cooldown, onCopy } = this.props; | ||||
| 
 | ||||
|     this.setState({ copied: true }); | ||||
|     setTimeout(() => { | ||||
|       this.setState({ copied: false }); | ||||
|     }, cooldown); | ||||
| 
 | ||||
|     this.setState({ | ||||
|       copied: true, | ||||
|       timeout: setTimeout(() => { | ||||
|         this.setState({ copied: false, timeout: null }); | ||||
|       }, cooldown) | ||||
|     }); | ||||
|     onCopy(); | ||||
|   } | ||||
| } | ||||
|  | ||||
| @ -24,8 +24,4 @@ | ||||
| 
 | ||||
| .copy { | ||||
|   margin-right: 0.5em; | ||||
| 
 | ||||
|   svg { | ||||
|     transition: all .5s ease-in-out; | ||||
|   } | ||||
| } | ||||
|  | ||||
| @ -15,11 +15,9 @@ | ||||
| // along with Parity.  If not, see <http://www.gnu.org/licenses/>.
 | ||||
| 
 | ||||
| import React, { Component, PropTypes } from 'react'; | ||||
| import { TextField } from 'material-ui'; | ||||
| 
 | ||||
| import CopyToClipboard from 'react-copy-to-clipboard'; | ||||
| import CopyIcon from 'material-ui/svg-icons/content/content-copy'; | ||||
| import { TextField, IconButton } from 'material-ui'; | ||||
| import { lightWhite, fullWhite } from 'material-ui/styles/colors'; | ||||
| import CopyToClipboard from '../../CopyToClipboard'; | ||||
| 
 | ||||
| import styles from './input.css'; | ||||
| 
 | ||||
| @ -77,9 +75,7 @@ export default class Input extends Component { | ||||
|   } | ||||
| 
 | ||||
|   state = { | ||||
|     value: this.props.value || '', | ||||
|     timeoutId: null, | ||||
|     copied: false | ||||
|     value: this.props.value || '' | ||||
|   } | ||||
| 
 | ||||
|   componentWillReceiveProps (newProps) { | ||||
| @ -88,14 +84,6 @@ export default class Input extends Component { | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   componentWillUnmount () { | ||||
|     const { timeoutId } = this.state; | ||||
| 
 | ||||
|     if (timeoutId) { | ||||
|       window.clearTimeout(timeoutId); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   render () { | ||||
|     const { value } = this.state; | ||||
|     const { children, className, hideUnderline, disabled, error, label, hint, multiLine, rows, type } = this.props; | ||||
| @ -151,7 +139,7 @@ export default class Input extends Component { | ||||
| 
 | ||||
|   renderCopyButton () { | ||||
|     const { allowCopy, hideUnderline, label, hint, floatCopy } = this.props; | ||||
|     const { copied, value } = this.state; | ||||
|     const { value } = this.state; | ||||
| 
 | ||||
|     if (!allowCopy) { | ||||
|       return null; | ||||
| @ -165,8 +153,6 @@ export default class Input extends Component { | ||||
|       ? allowCopy | ||||
|       : value; | ||||
| 
 | ||||
|     const scale = copied ? 'scale(1.15)' : 'scale(1)'; | ||||
| 
 | ||||
|     if (hideUnderline && !label) { | ||||
|       style.marginBottom = 2; | ||||
|     } else if (label && !hint) { | ||||
| @ -184,49 +170,11 @@ export default class Input extends Component { | ||||
| 
 | ||||
|     return ( | ||||
|       <div className={ styles.copy } style={ style }> | ||||
|         <CopyToClipboard | ||||
|           onCopy={ this.handleCopy } | ||||
|           text={ text } > | ||||
|           <IconButton | ||||
|             tooltip={ `${copied ? 'Copied' : 'Copy'} to clipboard` } | ||||
|             tooltipPosition='bottom-right' | ||||
|             style={ { | ||||
|               width: 16, | ||||
|               height: 16, | ||||
|               padding: 0 | ||||
|             } } | ||||
|             iconStyle={ { | ||||
|               width: 16, | ||||
|               height: 16, | ||||
|               transform: scale | ||||
|             } } | ||||
|             tooltipStyles={ { | ||||
|               top: 16 | ||||
|             } } | ||||
|           > | ||||
|             <CopyIcon | ||||
|               color={ copied ? lightWhite : fullWhite } | ||||
|             /> | ||||
|           </IconButton> | ||||
|         </CopyToClipboard> | ||||
|         <CopyToClipboard data={ text } /> | ||||
|       </div> | ||||
|     ); | ||||
|   } | ||||
| 
 | ||||
|   handleCopy = () => { | ||||
|     if (this.state.timeoutId) { | ||||
|       window.clearTimeout(this.state.timeoutId); | ||||
|     } | ||||
| 
 | ||||
|     this.setState({ copied: true }, () => { | ||||
|       const timeoutId = window.setTimeout(() => { | ||||
|         this.setState({ copied: false }); | ||||
|       }, 500); | ||||
| 
 | ||||
|       this.setState({ timeoutId }); | ||||
|     }); | ||||
|   } | ||||
| 
 | ||||
|   onChange = (event, value) => { | ||||
|     this.setValue(value); | ||||
| 
 | ||||
|  | ||||
| @ -43,6 +43,6 @@ | ||||
| } | ||||
| 
 | ||||
| .address { | ||||
|   white-space: nowrap; | ||||
|   font-family: monospace; | ||||
|   display: inline-block; | ||||
|   margin-left: .5em; | ||||
| } | ||||
|  | ||||
| @ -15,13 +15,9 @@ | ||||
| // along with Parity.  If not, see <http://www.gnu.org/licenses/>.
 | ||||
| 
 | ||||
| import React, { Component, PropTypes } from 'react'; | ||||
| import CopyToClipboard from 'react-copy-to-clipboard'; | ||||
| import IconButton from 'material-ui/IconButton'; | ||||
| import Snackbar from 'material-ui/Snackbar'; | ||||
| import CopyIcon from 'material-ui/svg-icons/content/content-copy'; | ||||
| import { lightWhite, fullWhite, darkBlack } from 'material-ui/styles/colors'; | ||||
| 
 | ||||
| import { Balance, Container, ContainerTitle, IdentityIcon, IdentityName, Tags } from '../../../ui'; | ||||
| import CopyToClipboard from '../../../ui/CopyToClipboard'; | ||||
| 
 | ||||
| import styles from './header.css'; | ||||
| 
 | ||||
| @ -37,8 +33,7 @@ export default class Header extends Component { | ||||
|   } | ||||
| 
 | ||||
|   state = { | ||||
|     name: null, | ||||
|     addressCopied: false | ||||
|     name: null | ||||
|   } | ||||
| 
 | ||||
|   componentWillMount () { | ||||
| @ -51,7 +46,6 @@ export default class Header extends Component { | ||||
| 
 | ||||
|   render () { | ||||
|     const { account, balance } = this.props; | ||||
|     const { addressCopied } = this.state; | ||||
|     const { address, meta, uuid } = account; | ||||
| 
 | ||||
|     if (!account) { | ||||
| @ -64,50 +58,14 @@ export default class Header extends Component { | ||||
| 
 | ||||
|     return ( | ||||
|       <div> | ||||
| 
 | ||||
|         <Snackbar | ||||
|           open={ addressCopied } | ||||
|           message={ | ||||
|             <span> | ||||
|               Address | ||||
|               <span className={ styles.address }> { address } </span> | ||||
|               copied to clipboard | ||||
|             </span> | ||||
|           } | ||||
|           autoHideDuration={ 4000 } | ||||
|           onRequestClose={ this.handleCopyAddressClose } | ||||
|           bodyStyle={ { | ||||
|             backgroundColor: darkBlack | ||||
|           } } | ||||
|         /> | ||||
| 
 | ||||
|         <Container> | ||||
|           <IdentityIcon | ||||
|             address={ address } /> | ||||
|           <div className={ styles.floatleft }> | ||||
|             <ContainerTitle title={ <IdentityName address={ address } unknown /> } /> | ||||
|             <div className={ styles.addressline }> | ||||
|               <CopyToClipboard | ||||
|                 onCopy={ this.handleCopyAddress } | ||||
|                 text={ address } > | ||||
|                 <IconButton | ||||
|                   tooltip='Copy address to clipboard' | ||||
|                   tooltipPosition='top-center' | ||||
|                   style={ { | ||||
|                     width: 32, | ||||
|                     height: 16, | ||||
|                     padding: 0 | ||||
|                   } } | ||||
|                   iconStyle={ { | ||||
|                     width: 16, | ||||
|                     height: 16 | ||||
|                   } }> | ||||
|                   <CopyIcon | ||||
|                     color={ addressCopied ? lightWhite : fullWhite } | ||||
|                   /> | ||||
|                 </IconButton> | ||||
|               </CopyToClipboard> | ||||
|               <span>{ address } </span> | ||||
|               <CopyToClipboard data={ address } /> | ||||
|               <div className={ styles.address }>{ address }</div> | ||||
|             </div> | ||||
|             { uuidText } | ||||
|             <div className={ styles.infoline }> | ||||
| @ -157,14 +115,6 @@ export default class Header extends Component { | ||||
|     }); | ||||
|   } | ||||
| 
 | ||||
|   handleCopyAddress = () => { | ||||
|     this.setState({ addressCopied: true }); | ||||
|   } | ||||
| 
 | ||||
|   handleCopyAddressClose = () => { | ||||
|     this.setState({ addressCopied: false }); | ||||
|   } | ||||
| 
 | ||||
|   setName () { | ||||
|     const { account } = this.props; | ||||
| 
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user