diff options
| author | Janito Vaqueiro Ferreira Filho <janito@mullvad.net> | 2018-07-24 13:11:41 -0300 |
|---|---|---|
| committer | Janito Vaqueiro Ferreira Filho <janito@mullvad.net> | 2018-07-24 13:12:43 -0300 |
| commit | 18b37cc66631bfbf17eded4d609c1ae12d5f6ccc (patch) | |
| tree | 878db7d308dc322abc5546ead569cd4c7e34023c | |
| parent | d1632102fbf53032b87fc8f6bcdc7299ee411b15 (diff) | |
| download | mullvadvpn-18b37cc66631bfbf17eded4d609c1ae12d5f6ccc.tar.xz mullvadvpn-18b37cc66631bfbf17eded4d609c1ae12d5f6ccc.zip | |
Copy account token to clipboard when clicked
| -rw-r--r-- | app/components/Account.js | 28 | ||||
| -rw-r--r-- | app/containers/AccountPage.js | 3 | ||||
| -rw-r--r-- | app/redux/account/actions.js | 12 | ||||
| -rw-r--r-- | test/components/Account.spec.js | 1 |
4 files changed, 43 insertions, 1 deletions
diff --git a/app/components/Account.js b/app/components/Account.js index 20435d48ba..9b6e1c8dea 100644 --- a/app/components/Account.js +++ b/app/components/Account.js @@ -17,6 +17,7 @@ export type AccountProps = { updateAccountExpiry: () => Promise<void>, onLogout: () => void, onClose: () => void, + onCopyAccountToken: () => void, onBuyMore: () => void, }; @@ -27,12 +28,15 @@ export type AccountState = { export default class Account extends Component<AccountProps, AccountState> { state = { isRefreshingExpiry: false, + showAccountCopiedMessage: false, }; _activationStateToken: ?Types.SubscriptionToken; _isMounted = false; + _copyTimer: ?TimeoutID; + componentDidMount() { this._isMounted = true; this._refreshAccountExpiry(); @@ -47,6 +51,10 @@ export default class Account extends Component<AccountProps, AccountState> { componentWillUnmount() { this._isMounted = false; + if (this._copyTimer) { + clearTimeout(this._copyTimer); + } + const activationStateToken = this._activationStateToken; if (activationStateToken) { activationStateToken.unsubscribe(); @@ -54,6 +62,18 @@ export default class Account extends Component<AccountProps, AccountState> { } } + onAccountTokenClick() { + if (this._copyTimer) { + clearTimeout(this._copyTimer); + } + this._copyTimer = setTimeout( + () => this.setState({ showAccountTokenCopiedMessage: false }), + 3000, + ); + this.setState({ showAccountTokenCopiedMessage: true }); + this.props.onCopyAccountToken(); + } + render() { const expiry = moment(this.props.accountExpiry); const formattedAccountToken = formatAccount(this.props.accountToken || ''); @@ -77,7 +97,13 @@ export default class Account extends Component<AccountProps, AccountState> { <View style={styles.account__main}> <View style={styles.account__row}> <Text style={styles.account__row_label}>Account ID</Text> - <Text style={styles.account__row_value}>{formattedAccountToken}</Text> + <Text + style={styles.account__row_value} + onPress={this.onAccountTokenClick.bind(this)}> + {this.state.showAccountTokenCopiedMessage + ? 'COPIED TO CLIPBOARD!' + : formattedAccountToken} + </Text> </View> <View style={styles.account__row}> diff --git a/app/containers/AccountPage.js b/app/containers/AccountPage.js index a8b54b30a3..2c23d326d8 100644 --- a/app/containers/AccountPage.js +++ b/app/containers/AccountPage.js @@ -4,6 +4,7 @@ import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; import { push } from 'react-router-redux'; import Account from '../components/Account'; +import accountActions from '../redux/account/actions'; import { links } from '../config'; import { openLink } from '../lib/platform'; @@ -15,9 +16,11 @@ const mapStateToProps = (state: ReduxState) => ({ accountExpiry: state.account.expiry, }); const mapDispatchToProps = (dispatch: ReduxDispatch, props: SharedRouteProps) => { + const { copyAccountToken } = bindActionCreators(accountActions, dispatch); const { push: pushHistory } = bindActionCreators({ push }, dispatch); return { updateAccountExpiry: () => props.app.updateAccountExpiry(), + onCopyAccountToken: () => copyAccountToken(), onLogout: () => { props.app.logout(); }, diff --git a/app/redux/account/actions.js b/app/redux/account/actions.js index 41fbfdee05..3cc4b83681 100644 --- a/app/redux/account/actions.js +++ b/app/redux/account/actions.js @@ -1,6 +1,17 @@ // @flow +import { Clipboard } from 'reactxp'; import type { AccountToken } from '../../lib/daemon-rpc'; +import type { ReduxThunk } from '../store'; + +const copyAccountToken = (): ReduxThunk => { + return (_, getState) => { + const accountToken = getState().account.accountToken; + if (accountToken) { + Clipboard.setText(accountToken); + } + }; +}; type StartLoginAction = { type: 'START_LOGIN', @@ -109,6 +120,7 @@ function updateAccountExpiry(expiry: string): UpdateAccountExpiryAction { } export default { + copyAccountToken, startLogin, loginSuccessful, loginFailed, diff --git a/test/components/Account.spec.js b/test/components/Account.spec.js index ef2ffe6d16..9d6e1cdbe8 100644 --- a/test/components/Account.spec.js +++ b/test/components/Account.spec.js @@ -12,6 +12,7 @@ describe('components/Account', () => { accountToken: '1234', accountExpiry: new Date('2038-01-01').toISOString(), updateAccountExpiry: () => Promise.resolve(), + onCopyAccountToken: () => {}, onClose: () => {}, onLogout: () => {}, onBuyMore: () => {}, |
