From 9b21c96e3aeff5aa2b5998a7a84354ea4c794c6a Mon Sep 17 00:00:00 2001 From: Nicolas Gotchac Date: Fri, 25 Nov 2016 15:52:23 +0100 Subject: [PATCH] Fix Copy to Clipboard Snackbar --- js/src/redux/providers/index.js | 1 + js/src/redux/providers/snackbarActions.js | 34 ++++++++++ js/src/redux/providers/snackbarReducer.js | 44 ++++++++++++ js/src/redux/reducers.js | 5 +- js/src/ui/CopyToClipboard/copyToClipboard.js | 43 ++++++++---- js/src/views/Application/Snackbar/index.js | 17 +++++ js/src/views/Application/Snackbar/snackbar.js | 68 +++++++++++++++++++ js/src/views/Application/application.js | 2 + 8 files changed, 197 insertions(+), 17 deletions(-) create mode 100644 js/src/redux/providers/snackbarActions.js create mode 100644 js/src/redux/providers/snackbarReducer.js create mode 100644 js/src/views/Application/Snackbar/index.js create mode 100644 js/src/views/Application/Snackbar/snackbar.js diff --git a/js/src/redux/providers/index.js b/js/src/redux/providers/index.js index 89064e740..d55b608eb 100644 --- a/js/src/redux/providers/index.js +++ b/js/src/redux/providers/index.js @@ -27,3 +27,4 @@ export signerReducer from './signerReducer'; export statusReducer from './statusReducer'; export blockchainReducer from './blockchainReducer'; export compilerReducer from './compilerReducer'; +export snackbarReducer from './snackbarReducer'; diff --git a/js/src/redux/providers/snackbarActions.js b/js/src/redux/providers/snackbarActions.js new file mode 100644 index 000000000..428958c4c --- /dev/null +++ b/js/src/redux/providers/snackbarActions.js @@ -0,0 +1,34 @@ +// 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 . + +export function showSnackbar (message, cooldown) { + return (dispatch, getState) => { + dispatch(openSnackbar(message, cooldown)); + }; +} + +function openSnackbar (message, cooldown) { + return { + type: 'openSnackbar', + message, cooldown + }; +} + +export function closeSnackbar () { + return { + type: 'closeSnackbar' + }; +} diff --git a/js/src/redux/providers/snackbarReducer.js b/js/src/redux/providers/snackbarReducer.js new file mode 100644 index 000000000..7a913f8ca --- /dev/null +++ b/js/src/redux/providers/snackbarReducer.js @@ -0,0 +1,44 @@ +// 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 . + +import { handleActions } from 'redux-actions'; + +const initialState = { + open: false, + message: '', + cooldown: 1000 +}; + +export default handleActions({ + openSnackbar (state, action) { + const { message, cooldown } = action; + + return { + ...state, + open: true, + cooldown: cooldown || state.cooldown, + message + }; + }, + + closeSnackbar (state) { + return { + ...state, + open: false, + cooldown: initialState.cooldown + }; + } +}, initialState); diff --git a/js/src/redux/reducers.js b/js/src/redux/reducers.js index 1365bdc99..923e32147 100644 --- a/js/src/redux/reducers.js +++ b/js/src/redux/reducers.js @@ -17,7 +17,7 @@ import { combineReducers } from 'redux'; import { routerReducer } from 'react-router-redux'; -import { apiReducer, balancesReducer, blockchainReducer, compilerReducer, imagesReducer, personalReducer, signerReducer, statusReducer as nodeStatusReducer } from './providers'; +import { apiReducer, balancesReducer, blockchainReducer, compilerReducer, imagesReducer, personalReducer, signerReducer, statusReducer as nodeStatusReducer, snackbarReducer } from './providers'; import { errorReducer } from '../ui/Errors'; import { settingsReducer } from '../views/Settings'; @@ -37,6 +37,7 @@ export default function () { images: imagesReducer, nodeStatus: nodeStatusReducer, personal: personalReducer, - signer: signerReducer + signer: signerReducer, + snackbar: snackbarReducer }); } diff --git a/js/src/ui/CopyToClipboard/copyToClipboard.js b/js/src/ui/CopyToClipboard/copyToClipboard.js index 568520b09..3ad316435 100644 --- a/js/src/ui/CopyToClipboard/copyToClipboard.js +++ b/js/src/ui/CopyToClipboard/copyToClipboard.js @@ -15,19 +15,25 @@ // along with Parity. If not, see . import React, { Component, PropTypes } from 'react'; +import { connect } from 'react-redux'; +import { bindActionCreators } from 'redux'; + 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'; + +import { showSnackbar } from '../../redux/providers/snackbarActions'; + const { textColor, disabledTextColor } = Theme.flatButton; import styles from './copyToClipboard.css'; -export default class CopyToClipboard extends Component { +class CopyToClipboard extends Component { static propTypes = { + showSnackbar: PropTypes.func.isRequired, data: PropTypes.string.isRequired, + onCopy: PropTypes.func, size: PropTypes.number, // in px cooldown: PropTypes.number // in ms @@ -42,11 +48,12 @@ export default class CopyToClipboard extends Component { state = { copied: false, - timeout: null + timeoutId: null }; componentWillUnmount () { const { timeoutId } = this.state; + if (timeoutId) { window.clearTimeout(timeoutId); } @@ -59,14 +66,6 @@ export default class CopyToClipboard extends Component { return (
- copied { data } to clipboard
- } - autoHideDuration={ 2000 } - bodyStyle={ { backgroundColor: darkBlack } } - /> { - const { cooldown, onCopy } = this.props; + const { data, onCopy, cooldown, showSnackbar } = this.props; + const message = (
copied { data } to clipboard
); this.setState({ copied: true, - timeout: setTimeout(() => { - this.setState({ copied: false, timeout: null }); + timeoutId: setTimeout(() => { + this.setState({ copied: false, timeoutId: null }); }, cooldown) }); + + showSnackbar(message, cooldown); onCopy(); } } + +function mapDispatchToProps (dispatch) { + return bindActionCreators({ + showSnackbar + }, dispatch); +} + +export default connect( + null, + mapDispatchToProps +)(CopyToClipboard); diff --git a/js/src/views/Application/Snackbar/index.js b/js/src/views/Application/Snackbar/index.js new file mode 100644 index 000000000..0da39f236 --- /dev/null +++ b/js/src/views/Application/Snackbar/index.js @@ -0,0 +1,17 @@ +// 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 . + +export default from './snackbar'; diff --git a/js/src/views/Application/Snackbar/snackbar.js b/js/src/views/Application/Snackbar/snackbar.js new file mode 100644 index 000000000..ac6e6b950 --- /dev/null +++ b/js/src/views/Application/Snackbar/snackbar.js @@ -0,0 +1,68 @@ +// 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 . + +import React, { Component, PropTypes } from 'react'; +import { connect } from 'react-redux'; +import { bindActionCreators } from 'redux'; + +import { Snackbar as SnackbarMUI } from 'material-ui'; +import { darkBlack } from 'material-ui/styles/colors'; + +import { closeSnackbar } from '../../../redux/providers/snackbarActions'; + +class Snackbar extends Component { + static propTypes = { + closeSnackbar: PropTypes.func.isRequired, + + open: PropTypes.bool, + cooldown: PropTypes.number, + message: PropTypes.any + }; + + render () { + const { open, message, cooldown } = this.props; + + return ( + + ); + } + + handleClose = () => { + this.props.closeSnackbar(); + } +} + +function mapStateToProps (state) { + const { open, message, cooldown } = state.snackbar; + return { open, message, cooldown }; +} + +function mapDispatchToProps (dispatch) { + return bindActionCreators({ + closeSnackbar + }, dispatch); +} + +export default connect( + mapStateToProps, + mapDispatchToProps +)(Snackbar); diff --git a/js/src/views/Application/application.js b/js/src/views/Application/application.js index d49aa5d90..0d5434534 100644 --- a/js/src/views/Application/application.js +++ b/js/src/views/Application/application.js @@ -21,6 +21,7 @@ import { bindActionCreators } from 'redux'; import Connection from '../Connection'; import ParityBar from '../ParityBar'; +import Snackbar from './Snackbar'; import Container from './Container'; import DappContainer from './DappContainer'; import FrameError from './FrameError'; @@ -87,6 +88,7 @@ class Application extends Component { pending={ pending } /> { children } { blockNumber ? () : null } + ); }