From 8ce841cfdb2494ad1a6fa0fd4b31fabecfc8e6ff Mon Sep 17 00:00:00 2001 From: meriadec Date: Fri, 29 Jun 2018 13:29:26 +0200 Subject: [PATCH 1/7] Add CopyWithFeedback component. Use it in OperationDetails modal. --- src/components/base/CopyWithFeedback.js | 79 +++++++++++++++++++++++ src/components/modals/OperationDetails.js | 54 ++++++---------- static/i18n/en/app.yml | 1 + static/i18n/fr/app.yml | 1 + 4 files changed, 100 insertions(+), 35 deletions(-) create mode 100644 src/components/base/CopyWithFeedback.js diff --git a/src/components/base/CopyWithFeedback.js b/src/components/base/CopyWithFeedback.js new file mode 100644 index 00000000..3ced0e88 --- /dev/null +++ b/src/components/base/CopyWithFeedback.js @@ -0,0 +1,79 @@ +// @flow + +import React, { PureComponent } from 'react' +import styled from 'styled-components' +import { translate } from 'react-i18next' + +import type { T } from 'types/common' + +import { darken, lighten } from 'styles/helpers' + +import IconCopy from 'icons/Copy' +import Box from 'components/base/Box' + +let clipboard = null + +if (!process.env.STORYBOOK_ENV) { + const electron = require('electron') + clipboard = electron.clipboard // eslint-disable-line +} + +type Props = { + t: T, + text: string, +} + +type State = { + isCopied: boolean, +} + +class CopyWithFeedback extends PureComponent { + state = { + isCopied: false, + } + + componentWillUnmount() { + this._isUnmounted = true + } + + _isUnmounted = false + + handleCopy = () => { + const { text } = this.props + clipboard && clipboard.writeText(text) + this.setState({ isCopied: true }) + setTimeout(() => { + this.setState({ isCopied: false }) + }, 1e3) + } + + render() { + const { t } = this.props + const { isCopied } = this.state + return ( + + + {isCopied ? t('app:common.copied') : t('app:common.copy')} + + ) + } +} + +const ClickableWrapper = styled(Box).attrs({ + horizontal: true, + align: 'center', + flow: 1, + color: 'wallet', + fontSize: 4, + ff: 'Open Sans|SemiBold', + cursor: 'pointer', +})` + &:hover { + color: ${p => lighten(p.theme.colors.wallet, 0.05)}; + } + &:active { + color: ${p => darken(p.theme.colors.wallet, 0.1)}; + } +` + +export default translate()(CopyWithFeedback) diff --git a/src/components/modals/OperationDetails.js b/src/components/modals/OperationDetails.js index 8110b92f..721acd26 100644 --- a/src/components/modals/OperationDetails.js +++ b/src/components/modals/OperationDetails.js @@ -16,7 +16,6 @@ import { MODAL_OPERATION_DETAILS } from 'config/constants' import { getMarketColor } from 'styles/helpers' import Box from 'components/base/Box' -import CopyToClipboard from 'components/base/CopyToClipboard' import GradientBox from 'components/GradientBox' import GrowScroll from 'components/base/GrowScroll' import Button from 'components/base/Button' @@ -24,12 +23,12 @@ import Bar from 'components/base/Bar' import FormattedVal from 'components/base/FormattedVal' import Modal, { ModalBody, ModalTitle, ModalFooter, ModalContent } from 'components/base/Modal' import Text from 'components/base/Text' +import CopyWithFeedback from 'components/base/CopyWithFeedback' import { createStructuredSelector, createSelector } from 'reselect' import { accountSelector } from 'reducers/accounts' import { currencySettingsForAccountSelector, marketIndicatorSelector } from 'reducers/settings' -import IconCopy from 'icons/Copy' import IconChevronRight from 'icons/ChevronRight' import CounterValue from 'components/CounterValue' import ConfirmationCheck from 'components/OperationsList/ConfirmationCheck' @@ -45,13 +44,9 @@ const OpDetailsTitle = styled(Box).attrs({ letter-spacing: 2px; ` -const CopyBtn = styled(Box).attrs({ - horizontal: true, - flow: 1, +const GradientHover = styled(Box).attrs({ align: 'center', color: 'wallet', - cursor: 'pointer', - ff: 'Open Sans|SemiBold', })` background: white; position: absolute; @@ -68,19 +63,15 @@ const OpDetailsData = styled(Box).attrs({ fontSize: 4, relative: true, })` - ${CopyBtn} { + ${GradientHover} { display: none; } - &:hover ${CopyBtn} { + &:hover ${GradientHover} { display: flex; } ` -const CanSelect = styled.div` - user-select: text; -` - const B = styled(Bar).attrs({ color: 'lightGrey', size: 1, @@ -216,16 +207,9 @@ const OperationDetails = connect(mapStateToProps)((props: Props) => { {t('app:operationDetails.identifier')} {hash} - - ( - - - {t('app:common.copy')} - - )} - /> + + + @@ -300,11 +284,14 @@ export class Recipients extends Component<{ recipients: Array<*>, t: T }, *> { const shouldShowMore = recipients.length > 3 return ( - - {(shouldShowMore ? recipients.slice(0, numToShow) : recipients).map(recipient => ( - {recipient} - ))} - + {(shouldShowMore ? recipients.slice(0, numToShow) : recipients).map(recipient => ( + + {recipient} + + + + + ))} {shouldShowMore && !showMore && ( @@ -314,13 +301,10 @@ export class Recipients extends Component<{ recipients: Array<*>, t: T }, *> { )} - {showMore && ( - - {recipients - .slice(numToShow) - .map(recipient => {recipient})} - - )} + {showMore && + recipients + .slice(numToShow) + .map(recipient => {recipient})} {shouldShowMore && showMore && ( diff --git a/static/i18n/en/app.yml b/static/i18n/en/app.yml index fa5c2385..a9514d11 100644 --- a/static/i18n/en/app.yml +++ b/static/i18n/en/app.yml @@ -35,6 +35,7 @@ common: reverify: Re-verify verify: Verify copy: Copy + copied: Copied! addressCopied: Address copied! lockScreen: title: Welcome back diff --git a/static/i18n/fr/app.yml b/static/i18n/fr/app.yml index 68304948..1f6f945c 100644 --- a/static/i18n/fr/app.yml +++ b/static/i18n/fr/app.yml @@ -35,6 +35,7 @@ common: reverify: Re-verify verify: Verify copy: Copy + copied: Copied! addressCopied: Address copied! lockScreen: title: Welcome back From 52f4398eb275411d9789a5b8a24f7245459a2ffc Mon Sep 17 00:00:00 2001 From: meriadec Date: Fri, 29 Jun 2018 13:35:20 +0200 Subject: [PATCH 2/7] Correct color for fees in OperationDetails --- src/components/modals/OperationDetails.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/modals/OperationDetails.js b/src/components/modals/OperationDetails.js index 721acd26..3ca174a2 100644 --- a/src/components/modals/OperationDetails.js +++ b/src/components/modals/OperationDetails.js @@ -183,7 +183,7 @@ const OperationDetails = connect(mapStateToProps)((props: Props) => { {fee ? ( - + ) : ( From 583baa2a6b38f0d99f0d4543c56650f9168b69f6 Mon Sep 17 00:00:00 2001 From: meriadec Date: Fri, 29 Jun 2018 13:39:40 +0200 Subject: [PATCH 3/7] Autofocus account name on AccountSettings --- src/components/modals/AccountSettingRenderBody.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/modals/AccountSettingRenderBody.js b/src/components/modals/AccountSettingRenderBody.js index a61dc966..236d4f4b 100644 --- a/src/components/modals/AccountSettingRenderBody.js +++ b/src/components/modals/AccountSettingRenderBody.js @@ -206,11 +206,11 @@ class HelperComp extends PureComponent { } onFocus={e => this.handleFocus(e, 'accountName')} error={accountNameError && t('app:account.settings.accountName.error')} /> From 453c22bc20e3d0c38d62c00b6656c74d4cc92fd3 Mon Sep 17 00:00:00 2001 From: meriadec Date: Fri, 29 Jun 2018 13:57:24 +0200 Subject: [PATCH 4/7] Update genuine check error style in onboarding --- src/components/Onboarding/helperComponents.js | 5 +++- .../GenuineCheck/GenuineCheckUnavailable.js | 26 +++++++++++-------- .../Onboarding/steps/GenuineCheck/index.js | 23 +++++++++++----- static/i18n/en/errors.yml | 2 +- 4 files changed, 37 insertions(+), 19 deletions(-) diff --git a/src/components/Onboarding/helperComponents.js b/src/components/Onboarding/helperComponents.js index d1d668f2..7a0e7d39 100644 --- a/src/components/Onboarding/helperComponents.js +++ b/src/components/Onboarding/helperComponents.js @@ -140,7 +140,10 @@ export const GenuineCheckCardWrapper = styled(Box).attrs({ height: 74px; transition: all ease-in-out 0.2s; color: ${p => (p.isDisabled ? p.theme.colors.grey : p.theme.colors.black)}; - border: ${p => `1px ${p.isDisabled ? 'dashed' : 'solid'} ${p.theme.colors.fog}`}; + border: ${p => + `1px ${p.isDisabled ? 'dashed' : 'solid'} ${ + p.isError ? p.theme.colors.alertRed : p.theme.colors.fog + }`}; pointer-events: ${p => (p.isDisabled ? 'none' : 'auto')}; background-color: ${p => (p.isDisabled ? p.theme.colors.lightGrey : p.theme.colors.white)}; opacity: ${p => (p.isDisabled ? 0.7 : 1)}; diff --git a/src/components/Onboarding/steps/GenuineCheck/GenuineCheckUnavailable.js b/src/components/Onboarding/steps/GenuineCheck/GenuineCheckUnavailable.js index 3e620983..5f248f57 100644 --- a/src/components/Onboarding/steps/GenuineCheck/GenuineCheckUnavailable.js +++ b/src/components/Onboarding/steps/GenuineCheck/GenuineCheckUnavailable.js @@ -7,7 +7,7 @@ import type { T } from 'types/common' import type { OnboardingState } from 'reducers/onboarding' import FakeLink from 'components/base/FakeLink' -import IconCross from 'icons/Cross' +import IconExclamationCircle from 'icons/ExclamationCircle' import Box from 'components/base/Box' import Button from 'components/base/Button' import TranslatedError from 'components/TranslatedError' @@ -57,9 +57,21 @@ export function GenuineCheckUnavailableMessage({ onboarding: OnboardingState, }) { return ( - + + + + + { @@ -72,14 +84,6 @@ export function GenuineCheckUnavailableMessage({ > {t('app:common.retry')} - - - - - - - - ) } diff --git a/src/components/Onboarding/steps/GenuineCheck/index.js b/src/components/Onboarding/steps/GenuineCheck/index.js index a599d720..36bd1f31 100644 --- a/src/components/Onboarding/steps/GenuineCheck/index.js +++ b/src/components/Onboarding/steps/GenuineCheck/index.js @@ -14,6 +14,7 @@ import Button from 'components/base/Button' import RadioGroup from 'components/base/RadioGroup' import GenuineCheckModal from 'components/GenuineCheckModal' +import IconCross from 'icons/Cross' import IconCheck from 'icons/Check' import { @@ -220,7 +221,10 @@ class GenuineCheck extends PureComponent { - + @@ -239,11 +243,9 @@ class GenuineCheck extends PureComponent { ) : genuine.genuineCheckUnavailable ? ( - + + + ) : ( @@ -76,11 +78,9 @@ export const Description = styled(Box).attrs({ ff: 'Open Sans|Regular', fontSize: 4, color: p => p.theme.colors.graphite, -})` - margin: 10px auto 25px; - display: block; - text-align: center; -` + textAlign: 'center', +})`` + export default compose( connect( null, From 6b68714ba6411d104bb982a67652e4d91346370b Mon Sep 17 00:00:00 2001 From: meriadec Date: Fri, 29 Jun 2018 14:51:40 +0200 Subject: [PATCH 6/7] Polish the DeviceInteraction error style --- src/components/DeviceInteraction/components.js | 15 ++++++++++++--- src/components/DeviceInteraction/index.js | 2 +- src/components/DeviceInteraction/stories.js | 1 + 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/components/DeviceInteraction/components.js b/src/components/DeviceInteraction/components.js index fe678da4..3477110a 100644 --- a/src/components/DeviceInteraction/components.js +++ b/src/components/DeviceInteraction/components.js @@ -100,12 +100,21 @@ export const ErrorDescContainer = ({ error: Error, onRetry: void => void, }) => ( - + - + - + {'Retry'} diff --git a/src/components/DeviceInteraction/index.js b/src/components/DeviceInteraction/index.js index b11e038b..0c261790 100644 --- a/src/components/DeviceInteraction/index.js +++ b/src/components/DeviceInteraction/index.js @@ -107,7 +107,7 @@ class DeviceInteraction extends PureComponent { ) })} {error && - shouldRenderRetry && } + shouldRenderRetry && } ) } diff --git a/src/components/DeviceInteraction/stories.js b/src/components/DeviceInteraction/stories.js index e111336b..2ae99f16 100644 --- a/src/components/DeviceInteraction/stories.js +++ b/src/components/DeviceInteraction/stories.js @@ -34,6 +34,7 @@ class Wrapper extends React.Component { {'reset'} (this._ref = n)} steps={[ { From 03ce5159c22ff0651f0c8fbd1283db4d8ff92a33 Mon Sep 17 00:00:00 2001 From: meriadec Date: Fri, 29 Jun 2018 15:11:09 +0200 Subject: [PATCH 7/7] Tooltip on lock --- src/components/TopBar/index.js | 8 +++++--- static/i18n/en/app.yml | 1 + 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/components/TopBar/index.js b/src/components/TopBar/index.js index 13d88557..de80eeb7 100644 --- a/src/components/TopBar/index.js +++ b/src/components/TopBar/index.js @@ -119,9 +119,11 @@ class TopBar extends PureComponent { - - - + t('app:common.lock')}> + + + + )} diff --git a/static/i18n/en/app.yml b/static/i18n/en/app.yml index a9514d11..79ed9fcd 100644 --- a/static/i18n/en/app.yml +++ b/static/i18n/en/app.yml @@ -21,6 +21,7 @@ common: save: Save password: Password editProfile: Preferences + lock: Lock lockApplication: Lock Ledger Live showMore: Show more max: Max