diff --git a/src/components/DeviceConnect/index.js b/src/components/DeviceConnect/index.js index 13b7d5d7..c693625f 100644 --- a/src/components/DeviceConnect/index.js +++ b/src/components/DeviceConnect/index.js @@ -17,6 +17,7 @@ import IconExclamationCircle from 'icons/ExclamationCircle' import IconInfoCircle from 'icons/InfoCircle' import IconLoader from 'icons/Loader' import IconUsb from 'icons/Usb' +import IconHome from 'icons/Home' import * as IconDevice from 'icons/device' @@ -33,12 +34,14 @@ const Step = styled(Box).attrs({ ? p.theme.colors.alertRed : p.theme.colors.fog}; ` + const StepIcon = styled(Box).attrs({ alignItems: 'center', justifyContent: 'center', })` width: 64px; ` + const StepContent = styled(Box).attrs({ color: 'dark', horizontal: true, @@ -138,6 +141,8 @@ StepCheck.defaultProps = { type Props = { accountName: null | string, appOpened: null | 'success' | 'fail', + genuineCheckStatus: null | 'success' | 'fail', + withGenuineCheck: boolean, currency: CryptoCurrency, devices: Device[], deviceSelected: ?Device, @@ -161,6 +166,7 @@ class DeviceConnect extends PureComponent { devices: [], deviceSelected: null, onChangeDevice: noop, + withGenuineCheck: false, } componentDidMount() { @@ -171,18 +177,17 @@ class DeviceConnect extends PureComponent { emitChangeDevice(nextProps) } - getAppState() { - const { appOpened } = this.props - - return { - success: appOpened === 'success', - fail: appOpened === 'fail', - } - } + getStepState = stepStatus => ({ + success: stepStatus === 'success', + fail: stepStatus === 'fail', + }) render() { const { deviceSelected, + genuineCheckStatus, + withGenuineCheck, + appOpened, errorMessage, accountName, currency, @@ -191,7 +196,8 @@ class DeviceConnect extends PureComponent { devices, } = this.props - const appState = this.getAppState() + const appState = this.getStepState(appOpened) + const genuineCheckState = this.getStepState(genuineCheckStatus) const hasDevice = devices.length > 0 const hasMultipleDevices = devices.length > 1 @@ -242,24 +248,66 @@ class DeviceConnect extends PureComponent { )} + - - - - - - - - - {'Open '} - {currency.name} - {' App on your device'} - - - - + {currency ? ( + + + + + + + + + {'Open '} + {currency.name} + {' App on your device'} + + + + + ) : ( + + + + + + + + + {'Go to the '} + {'dashboard'} + {' on your device'} + + + + + )} + {/* GENUINE CHECK */} + {/* ------------- */} + + {withGenuineCheck && ( + + + + + + + + + + {'Confirm '} + {'authentication'} + {' on your device'} + + + + + + )} + {appState.fail ? ( diff --git a/src/components/EnsureDeviceApp/index.js b/src/components/EnsureDeviceApp/index.js index 17af125d..bce04b25 100644 --- a/src/components/EnsureDeviceApp/index.js +++ b/src/components/EnsureDeviceApp/index.js @@ -1,5 +1,4 @@ // @flow -import invariant from 'invariant' import { PureComponent } from 'react' import { connect } from 'react-redux' import { standardDerivation } from 'helpers/derivations' @@ -12,14 +11,17 @@ import type { State as StoreState } from 'reducers/index' import getAddress from 'commands/getAddress' type OwnProps = { - currency: ?CryptoCurrency, + currency?: ?CryptoCurrency, deviceSelected: ?Device, - account: ?Account, + withGenuineCheck?: boolean, + account?: ?Account, onStatusChange?: (DeviceStatus, AppStatus, ?string) => void, + onGenuineCheck?: (isGenuine: boolean) => void, // TODO prefer children function render?: ({ appStatus: AppStatus, - currency: CryptoCurrency, + genuineCheckStatus: GenuineCheckStatus, + currency: ?CryptoCurrency, devices: Device[], deviceSelected: ?Device, deviceStatus: DeviceStatus, @@ -35,10 +37,13 @@ type DeviceStatus = 'unconnected' | 'connected' type AppStatus = 'success' | 'fail' | 'progress' +type GenuineCheckStatus = 'success' | 'fail' | 'progress' + type State = { deviceStatus: DeviceStatus, appStatus: AppStatus, errorMessage: ?string, + genuineCheckStatus: GenuineCheckStatus, } const mapStateToProps = (state: StoreState) => ({ @@ -50,6 +55,7 @@ class EnsureDeviceApp extends PureComponent { appStatus: 'progress', deviceStatus: this.props.deviceSelected ? 'connected' : 'unconnected', errorMessage: null, + genuineCheckStatus: 'progress', } componentDidMount() { @@ -87,19 +93,21 @@ class EnsureDeviceApp extends PureComponent { componentWillUnmount() { clearTimeout(this._timeout) + this._unmounted = true } checkAppOpened = async () => { - const { deviceSelected, account, currency } = this.props + const { deviceSelected, account, currency, withGenuineCheck } = this.props + const { appStatus } = this.state if (!deviceSelected) { return } - let options + let appOptions if (account) { - options = { + appOptions = { devicePath: deviceSelected.path, currencyId: account.currency.id, path: account.freshAddressPath, @@ -107,21 +115,31 @@ class EnsureDeviceApp extends PureComponent { segwit: !!account.isSegwit, } } else if (currency) { - options = { + appOptions = { devicePath: deviceSelected.path, currencyId: currency.id, path: standardDerivation({ currency, x: 0, segwit: false }), } - } else { - throw new Error('either currency or account is required') } try { - const { address } = await getAddress.send(options).toPromise() - if (account && account.freshAddress !== address) { - throw new Error('Account address is different than device address') + if (appOptions) { + const { address } = await getAddress.send(appOptions).toPromise() + if (account && account.freshAddress !== address) { + throw new Error('Account address is different than device address') + } + } else { + // TODO: real check if user is on the device dashboard + if (!deviceSelected) { + throw new Error('No device') + } + await sleep(1) } this.handleStatusChange(this.state.deviceStatus, 'success') + + if (withGenuineCheck && appStatus !== 'success') { + this.handleGenuineCheck() + } } catch (e) { this.handleStatusChange(this.state.deviceStatus, 'fail', e.message) } @@ -130,27 +148,42 @@ class EnsureDeviceApp extends PureComponent { } _timeout: * + _unmounted = false handleStatusChange = (deviceStatus, appStatus, errorMessage = null) => { const { onStatusChange } = this.props clearTimeout(this._timeout) - this.setState({ deviceStatus, appStatus, errorMessage }) - onStatusChange && onStatusChange(deviceStatus, appStatus, errorMessage) + if (!this._unmounted) { + this.setState({ deviceStatus, appStatus, errorMessage }) + onStatusChange && onStatusChange(deviceStatus, appStatus, errorMessage) + } + } + + handleGenuineCheck = async () => { + // TODO: do a *real* genuine check + await sleep(1) + if (!this._unmounted) { + this.setState({ genuineCheckStatus: 'success' }) + this.props.onGenuineCheck && this.props.onGenuineCheck(true) + } } render() { const { currency, account, devices, deviceSelected, render } = this.props - const { appStatus, deviceStatus, errorMessage } = this.state + const { appStatus, deviceStatus, genuineCheckStatus, errorMessage } = this.state if (render) { + // if cur is not provided, we assume we want to check if user is on + // the dashboard const cur = account ? account.currency : currency - invariant(cur, 'currency is either provided or taken from account') + return render({ appStatus, currency: cur, devices, deviceSelected: deviceStatus === 'connected' ? deviceSelected : null, deviceStatus, + genuineCheckStatus, errorMessage, }) } @@ -160,3 +193,7 @@ class EnsureDeviceApp extends PureComponent { } export default connect(mapStateToProps)(EnsureDeviceApp) + +async function sleep(s) { + return new Promise(resolve => setTimeout(resolve, s * 1e3)) +} diff --git a/src/components/GenuineCheckModal/index.js b/src/components/GenuineCheckModal/index.js new file mode 100644 index 00000000..b80fe0d9 --- /dev/null +++ b/src/components/GenuineCheckModal/index.js @@ -0,0 +1,71 @@ +// @flow + +import React, { PureComponent } from 'react' +import { compose } from 'redux' +import { connect } from 'react-redux' +import { translate } from 'react-i18next' + +import type { T, Device } from 'types/common' + +import { getCurrentDevice } from 'reducers/devices' + +import DeviceConnect from 'components/DeviceConnect' +import EnsureDeviceApp from 'components/EnsureDeviceApp' +import Modal, { ModalBody, ModalTitle, ModalContent } from 'components/base/Modal' + +const mapStateToProps = state => ({ + currentDevice: getCurrentDevice(state), +}) + +type Props = { + t: T, + currentDevice: ?Device, + onGenuineCheck: (isGenuine: boolean) => void, +} + +type State = {} + +class GenuineCheck extends PureComponent { + renderBody = ({ onClose }) => { + const { t, currentDevice, onGenuineCheck } = this.props + + // TODO: use the real devices list. for now we force choosing only + // the current device because we don't handle multi device in MVP + const reducedDevicesList = currentDevice ? [currentDevice] : [] + + return ( + + {t('genuinecheck:modal.title')} + + { + console.log(`status changed to ${status}`) + }} + render={({ appStatus, genuineCheckStatus, deviceSelected, errorMessage }) => ( + + )} + /> + + + ) + } + + render() { + const { ...props } = this.props + return this.renderBody({ onClose })} /> + } +} + +export default compose(connect(mapStateToProps), translate())(GenuineCheck) diff --git a/src/components/Onboarding/helperComponents.js b/src/components/Onboarding/helperComponents.js index f7d8c312..689358d3 100644 --- a/src/components/Onboarding/helperComponents.js +++ b/src/components/Onboarding/helperComponents.js @@ -16,8 +16,6 @@ export const Title = styled(Box).attrs({ })`` export const Description = styled(Box).attrs({ - width: 714, - height: 48, ff: 'Museo Sans|Light', fontSize: 5, lineHeight: 1.5, @@ -25,6 +23,7 @@ export const Description = styled(Box).attrs({ color: 'grey', })` margin: 10px auto 25px; + max-width: 550px; ` export const Inner = styled(Box).attrs({ horizontal: true, diff --git a/src/components/Onboarding/index.js b/src/components/Onboarding/index.js index a3b5e1c5..1efdff9d 100644 --- a/src/components/Onboarding/index.js +++ b/src/components/Onboarding/index.js @@ -10,11 +10,16 @@ import type { T } from 'types/common' import type { OnboardingState } from 'reducers/onboarding' import { saveSettings } from 'actions/settings' -import { nextStep, prevStep, jumpStep, setGenuineCheckFail } from 'reducers/onboarding' +import { + nextStep, + prevStep, + jumpStep, + setGenuineCheckFail, + isLedgerNano, +} from 'reducers/onboarding' import { getCurrentDevice } from 'reducers/devices' -// TODO: re-write it without auto lock, fixed width of the password modal, not dynamic titles -import { unlock } from 'reducers/application' +// import { unlock } from 'reducers/application' import Box from 'components/base/Box' @@ -25,7 +30,8 @@ import SelectDevice from './steps/SelectDevice' import SelectPIN from './steps/SelectPIN' import WriteSeed from './steps/WriteSeed' import GenuineCheck from './steps/GenuineCheck' -import SetPassword from './steps/SetPassword' +// UNTIL IS NEEDED SET PASSWORD IS COMMENTED OUT +// import SetPassword from './steps/SetPassword' import Analytics from './steps/Analytics' import Finish from './steps/Finish' @@ -35,7 +41,7 @@ const STEPS = { selectPIN: SelectPIN, writeSeed: WriteSeed, genuineCheck: GenuineCheck, - setPassword: SetPassword, + // setPassword: SetPassword, analytics: Analytics, finish: Finish, start: Start, @@ -52,7 +58,7 @@ const mapDispatchToProps = { nextStep, prevStep, jumpStep, - unlock, + // unlock, } type Props = { @@ -74,23 +80,24 @@ export type StepProps = { nextStep: Function, jumpStep: Function, finish: Function, - savePassword: Function, + // savePassword: Function, getDeviceInfo: Function, setGenuineCheckFail: Function, + isLedgerNano: Function, } class Onboarding extends PureComponent { getDeviceInfo = () => this.props.getCurrentDevice finish = () => this.props.saveSettings({ hasCompletedOnboarding: true }) - savePassword = hash => { - this.props.saveSettings({ - password: { - isEnabled: hash !== undefined, - value: hash, - }, - }) - this.props.unlock() - } + // savePassword = hash => { + // this.props.saveSettings({ + // password: { + // isEnabled: hash !== undefined, + // value: hash, + // }, + // }) + // this.props.unlock() + // } render() { const { hasCompletedOnboarding, onboarding, prevStep, nextStep, jumpStep, t } = this.props @@ -110,11 +117,12 @@ class Onboarding extends PureComponent { t, onboarding, setGenuineCheckFail, + isLedgerNano, prevStep, nextStep, jumpStep, finish: this.finish, - savePassword: this.savePassword, + // savePassword: this.savePassword, getDeviceInfo: this.getDeviceInfo, } diff --git a/src/components/Onboarding/steps/Analytics.js b/src/components/Onboarding/steps/Analytics.js index 32ed6d1a..f46e1c76 100644 --- a/src/components/Onboarding/steps/Analytics.js +++ b/src/components/Onboarding/steps/Analytics.js @@ -4,7 +4,6 @@ import React from 'react' import styled from 'styled-components' import Box from 'components/base/Box' -import IconAnalytics from 'icons/onboarding/Analytics' import CheckBox from 'components/base/CheckBox' import { Title, Description } from '../helperComponents' import OnboardingFooter from '../OnboardingFooter' @@ -17,25 +16,31 @@ export default (props: StepProps) => { {t('onboarding:analytics.title')} - {t('onboarding:analytics.desc')} - - - - - - - This is a long text, please replace it with the final wording once it’s done. -
- Lorem ipsum dolor amet ledger lorem dolor ipsum amet -
-
- - - - This is a long text, please replace it with the final wording once it’s done. -
- Lorem ipsum dolor amet ledger lorem dolor ipsum amet -
+ {t('onboarding:analytics.desc')} + + + + + + {t('onboarding:analytics.shareDiagnostics.title')} + + {t('onboarding:analytics.shareDiagnostics.desc')} + + + + + + + + + {t('onboarding:analytics.shareDiagnostics.title')} + + {t('onboarding:analytics.shareDiagnostics.desc')} + + + + +
{ export const AnalyticsText = styled(Box).attrs({ ff: 'Open Sans|Regular', - fontSize: 4, + fontSize: 3, textAlign: 'left', color: 'smoke', })` - margin: 10px auto 25px; - padding-left: 10px; + max-width: 450px; +` +export const AnalyticsTitle = styled(Box).attrs({ + ff: 'Open Sans|SemiBold', + fontSize: 4, + textAlign: 'left', +})` + margin-bottom: 5px; ` -const DeviceIcon = styled(Box).attrs({ - alignItems: 'center', - justifyContent: 'center', - color: 'graphite', +const Container = styled(Box).attrs({ + horizontal: true, + p: 5, })` - width: 55px; + max-height: 90px; + width: 620px; ` diff --git a/src/components/Onboarding/steps/GenuineCheck.js b/src/components/Onboarding/steps/GenuineCheck.js index fa7f061a..4ed6fcb5 100644 --- a/src/components/Onboarding/steps/GenuineCheck.js +++ b/src/components/Onboarding/steps/GenuineCheck.js @@ -1,9 +1,9 @@ // @flow -import React, { PureComponent } from 'react' +import React, { PureComponent, Fragment } from 'react' import { connect } from 'react-redux' import styled from 'styled-components' -import { radii, colors } from 'styles/theme' +import { radii } from 'styles/theme' import type { T } from 'types/common' @@ -11,8 +11,12 @@ import { setGenuineCheckFail } from 'reducers/onboarding' import Box, { Card } from 'components/base/Box' import Button from 'components/base/Button' -import IconCheck from 'icons/Check' +import RadioGroup from 'components/base/RadioGroup' +import GenuineCheckModal from 'components/GenuineCheckModal' + import IconLedgerNanoError from 'icons/onboarding/LedgerNanoError' +import IconLedgerBlueError from 'icons/onboarding/LedgerBlueError' +import IconCheck from 'icons/Check' import { Title, Description, IconOptionRow } from '../helperComponents' @@ -24,39 +28,87 @@ const mapDispatchToProps = { setGenuineCheckFail } type State = { pinStepPass: boolean | null, phraseStepPass: boolean | null, + cachedPinStepButton: string, + cachedPhraseStepButton: string, + isGenuineCheckModalOpened: boolean, + isDeviceGenuine: boolean, } class GenuineCheck extends PureComponent { state = { pinStepPass: null, phraseStepPass: null, + cachedPinStepButton: '', + cachedPhraseStepButton: '', + isGenuineCheckModalOpened: false, + isDeviceGenuine: false, } - handleStepPass = (step: string, pass: boolean | null) => { - this.setState({ [`${step}`]: pass }) + getButtonLabel() { + const { t } = this.props + return [ + { + label: t('common:yes'), + key: 'yes', + pass: true, + }, + { + label: t('common:no'), + key: 'no', + pass: false, + }, + ] + } + + handleButtonPass = (item: Object, step: string) => { + this.setState({ [`${step}`]: item.pass }) + if (step === 'pinStepPass') { + this.setState({ cachedPinStepButton: item.key }) + } else { + this.setState({ cachedPhraseStepButton: item.key }) + } - if (typeof pass === 'boolean' && !pass) { + if (!item.pass) { this.props.setGenuineCheckFail(true) } } + handleOpenGenuineCheckModal = () => this.setState({ isGenuineCheckModalOpened: true }) + handleCloseGenuineCheckModal = () => this.setState({ isGenuineCheckModalOpened: false }) + + handleGenuineCheck = async isGenuine => { + await new Promise(r => setTimeout(r, 1e3)) // let's wait a bit before closing modal + this.handleCloseGenuineCheckModal() + this.setState({ isDeviceGenuine: isGenuine }) + } + redoGenuineCheck = () => { this.props.setGenuineCheckFail(false) } + contactSupport = () => { console.log('contact support coming later') } + renderGenuineFail = () => ( ) render() { const { nextStep, prevStep, t, onboarding } = this.props - const { pinStepPass, phraseStepPass } = this.state + const { + pinStepPass, + phraseStepPass, + cachedPinStepButton, + cachedPhraseStepButton, + isGenuineCheckModalOpened, + isDeviceGenuine, + } = this.state if (onboarding.isGenuineFail) { return this.renderGenuineFail() @@ -76,22 +128,16 @@ class GenuineCheck extends PureComponent {
{t('onboarding:genuineCheck.steps.step2.desc')}
- {!pinStepPass ? ( - - ) : ( - - - - )} + this.handleButtonPass(item, 'pinStepPass')} + />
- + 2. @@ -99,22 +145,16 @@ class GenuineCheck extends PureComponent { {t('onboarding:genuineCheck.steps.step2.desc')} - {!phraseStepPass ? ( - - ) : ( - - - - )} + this.handleButtonPass(item, 'phraseStepPass')} + /> - + 3. @@ -123,8 +163,20 @@ class GenuineCheck extends PureComponent { {t('onboarding:genuineCheck.steps.step3.desc')} - @@ -138,6 +190,11 @@ class GenuineCheck extends PureComponent { nextStep={nextStep} prevStep={prevStep} /> + ) } @@ -145,58 +202,42 @@ class GenuineCheck extends PureComponent { export default connect(null, mapDispatchToProps)(GenuineCheck) -export function ButtonCombo({ - handleStepPass, - step, - disabled, - t, -}: { - handleStepPass: any, - step: string, - disabled: boolean, - t: T, -}) { - return ( - - - - - ) -} // TODO extract to a separate file export function GenuineCheckFail({ redoGenuineCheck, contactSupport, + isLedgerNano, t, }: { redoGenuineCheck: () => void, contactSupport: () => void, + isLedgerNano: boolean, t: T, }) { return ( - + - {t('onboarding:genuineCheck.errorPage.ledgerNano.title')} - - {t('onboarding:genuineCheck.errorPage.ledgerNano.desc')} - - - - + {isLedgerNano ? ( + + {t('onboarding:genuineCheck.errorPage.ledgerNano.title')} + + {t('onboarding:genuineCheck.errorPage.ledgerNano.desc')} + + + + + + ) : ( + + {t('onboarding:genuineCheck.errorPage.ledgerBlue.title')} + + {t('onboarding:genuineCheck.errorPage.ledgerBlue.desc')} + + + + + + )} - - {/* we might not be able to re-use what we have currently without modifications - the title and descriptions are not dynamic, we might need deffirent size as well */} - {isPasswordModalOpened && ( - - )} - nextStep()} style={{ padding: 15 }}> - - - - - - ) - } -} - -export default SetPassword +// // @flow +// +// import React, { PureComponent } from 'react' +// import bcrypt from 'bcryptjs' +// +// import { setEncryptionKey } from 'helpers/db' +// +// import Box from 'components/base/Box' +// import Button from 'components/base/Button' +// +// import IconSetPassword from 'icons/onboarding/SetPassword' +// import PasswordModal from 'components/SettingsPage/PasswordModal' +// import OnboardingFooter from '../OnboardingFooter' +// +// import type { StepProps } from '..' +// +// import { Title, Description } from '../helperComponents' +// +// type State = { +// isPasswordModalOpened: boolean, +// isPasswordEnabled: boolean, +// } +// +// class SetPassword extends PureComponent { +// state = { +// isPasswordModalOpened: false, +// isPasswordEnabled: false, +// } +// +// handleOpenPasswordModal = () => { +// this.setState({ isPasswordModalOpened: true }) +// } +// handleClosePasswordModal = () => { +// this.setState({ isPasswordModalOpened: false }) +// } +// handleChangePassword = (password: string) => { +// window.requestIdleCallback(() => { +// setEncryptionKey('accounts', password) +// const hash = password ? bcrypt.hashSync(password, 8) : undefined +// this.props.savePassword(hash) +// }) +// } +// +// handleInputChange = (key: string) => (value: string) => { +// this.setState({ [key]: value }) +// } +// +// render() { +// const { nextStep, prevStep, t } = this.props +// const { isPasswordModalOpened, isPasswordEnabled } = this.state +// return ( +// +// +// {t('onboarding:setPassword.title')} +// {t('onboarding:setPassword.desc')} +// +// +// +// +// {/* we might not be able to re-use what we have currently without modifications +// the title and descriptions are not dynamic, we might need deffirent size as well */} +// {isPasswordModalOpened && ( +// +// )} +// nextStep()} style={{ padding: 15 }}> +// +// +// +// +// +// ) +// } +// } +// +// export default SetPassword diff --git a/src/components/Onboarding/steps/WriteSeed.js b/src/components/Onboarding/steps/WriteSeed.js index d7378458..21828931 100644 --- a/src/components/Onboarding/steps/WriteSeed.js +++ b/src/components/Onboarding/steps/WriteSeed.js @@ -60,7 +60,7 @@ export default (props: StepProps) => { {t('onboarding:writeSeed.title')} - {t('onboarding:writeSeed.desc')} + {t('onboarding:writeSeed.desc')} diff --git a/src/components/base/InputPassword/index.js b/src/components/base/InputPassword/index.js index 84bc6656..f7c83865 100644 --- a/src/components/base/InputPassword/index.js +++ b/src/components/base/InputPassword/index.js @@ -106,7 +106,7 @@ class InputPassword extends PureComponent { {withStrength && ( - {[0, 1, 2, 3, 4].map(v => ( + {[0, 1, 2].map(v => ( +) + +export default ({ size, ...p }: { size: number }) => ( + + {path} + +) diff --git a/src/icons/onboarding/LedgerBlueError.js b/src/icons/onboarding/LedgerBlueError.js new file mode 100644 index 00000000..c668b490 --- /dev/null +++ b/src/icons/onboarding/LedgerBlueError.js @@ -0,0 +1,47 @@ +// @flow + +import React from 'react' + +export default () => ( + + + + + + + + + + + + + + + + + +) diff --git a/src/icons/onboarding/LedgerBlueSelectPIN.js b/src/icons/onboarding/LedgerBlueSelectPIN.js new file mode 100644 index 00000000..2391fe05 --- /dev/null +++ b/src/icons/onboarding/LedgerBlueSelectPIN.js @@ -0,0 +1,47 @@ +// @flow + +import React from 'react' + +export default () => ( + + + + + + + + + + + + + + + + + +) diff --git a/src/icons/onboarding/LedgerNano.js b/src/icons/onboarding/LedgerNano.js index 813ea82f..634bd32b 100644 --- a/src/icons/onboarding/LedgerNano.js +++ b/src/icons/onboarding/LedgerNano.js @@ -3,22 +3,22 @@ import React from 'react' export default () => ( - - - - + + + + ( fill="#FFF" stroke="#1D2028" strokeWidth="1.5" - d="M9.6 48.75A8.85 8.85 0 0 0 .75 57.6v52.8c0 .47.38.85.85.85h16c.47 0 .85-.38.85-.85V57.6a8.85 8.85 0 0 0-8.85-8.85z" + d="M6.24 31.607a5.49 5.49 0 0 0-5.49 5.49V70.4c0 .47.38.85.85.85h9.28c.47 0 .85-.38.85-.85V37.097a5.49 5.49 0 0 0-5.49-5.49z" + /> + - ) diff --git a/src/icons/onboarding/SelectPIN.js b/src/icons/onboarding/LedgerNanoSelectPIN.js similarity index 100% rename from src/icons/onboarding/SelectPIN.js rename to src/icons/onboarding/LedgerNanoSelectPIN.js diff --git a/src/icons/onboarding/WriteSeed.js b/src/icons/onboarding/WriteSeed.js index a802e9ba..248611a3 100644 --- a/src/icons/onboarding/WriteSeed.js +++ b/src/icons/onboarding/WriteSeed.js @@ -3,195 +3,43 @@ import React from 'react' export default () => ( - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - - - - - - - - - - - - - - - - - - - - - - + {/* + + RECOVERY PHRASE + + */} + ) diff --git a/src/reducers/onboarding.js b/src/reducers/onboarding.js index 97993271..86bc857e 100644 --- a/src/reducers/onboarding.js +++ b/src/reducers/onboarding.js @@ -18,12 +18,14 @@ export type OnboardingState = { stepName: string, // TODO: specify that the string comes from Steps type steps: Step[], isGenuineFail: boolean, + isLedgerNano: boolean, } const state: OnboardingState = { stepIndex: 0, stepName: 'start', isGenuineFail: false, + isLedgerNano: true, steps: [ { name: 'start', @@ -79,15 +81,16 @@ const state: OnboardingState = { showBreadcrumb: true, }, }, - { - name: 'setPassword', - label: 'Set Password', - options: { - showFooter: false, - showBackground: true, - showBreadcrumb: true, - }, - }, + // UNTIL IS NEEDED SET PASSWORD IS COMMENTED OUT + // { + // name: 'setPassword', + // label: 'Set Password', + // options: { + // showFooter: false, + // showBackground: true, + // showBreadcrumb: true, + // }, + // }, { name: 'analytics', label: 'Analytics & Bug report', @@ -144,6 +147,10 @@ const handlers = { ...state, isGenuineFail, }), + ONBOARDING_SET_DEVICE_TYPE: (state, { payload: isLedgerNano }) => ({ + ...state, + isLedgerNano, + }), } export default handleActions(handlers, state) @@ -152,3 +159,4 @@ export const nextStep = createAction('ONBOARDING_NEXT_STEP') export const prevStep = createAction('ONBOARDING_PREV_STEP') export const jumpStep = createAction('ONBOARDING_JUMP_STEP') export const setGenuineCheckFail = createAction('ONBOARDING_SET_GENUINE_CHECK_FAIL') +export const isLedgerNano = createAction('ONBOARDING_SET_DEVICE_TYPE') diff --git a/static/i18n/en/genuinecheck.yml b/static/i18n/en/genuinecheck.yml new file mode 100644 index 00000000..b6ecfcf5 --- /dev/null +++ b/static/i18n/en/genuinecheck.yml @@ -0,0 +1,2 @@ +modal: + title: Genuine check, bro diff --git a/static/i18n/en/onboarding.yml b/static/i18n/en/onboarding.yml index 882b2993..bcef3cf3 100644 --- a/static/i18n/en/onboarding.yml +++ b/static/i18n/en/onboarding.yml @@ -25,13 +25,17 @@ selectDevice: title: Ledger Blue desc: Please replace it with the final wording once it’s done. selectPIN: - title: Choose your PIN code - desc: This is a long text, please replace it with the final wording once it’s done. Lorem ipsum dolor amet ledger lorem dolor ipsum amet + title: Start initialization & choose your PIN code instructions: - step1: Connect the Ledger Nano S to your computer. - step2: Press both buttons simultaneously as instructed on the screen. - step3: Press the right button to select Configure as new device. - step4: Choose a PIN code between 4 and 8 digits long. + ledgerNano: + step1: Connect the Ledger Nano S to your computer. + step2: Press both buttons simultaneously as instructed on the screen. + step3: Press the right button to select Configure as new device. + step4: Choose a PIN code between 4 and 8 digits long. + ledgerBlue: + step1: Connect the Ledger Blue to your computer. + step2: Tap on Configure as new device. + step3: Choose a PIN code between 4 and 8 digits long. disclaimer: note1: Choose your own PIN code. This code unlocks your device. note2: An 8-digit PIN code offers an optimum level of security. @@ -49,31 +53,41 @@ writeSeed: note3: Make sure you are the sole holder of the 24-word recovery phrase. note4: Never use a device supplied with a recovery phrase and/or a PIN code. genuineCheck: - title: Check PIN / Seed / Authenticity + title: Final security check desc: Your Ledger Nano S should now display Your device is now ready. Before getting started, please confirm that steps: step1: - title: You alone have chosen your PIN code + title: Did you choose your PIN code by yourself? desc: This is a long text, please replace it with the final wording once it’s done. Lorem ipsum dolor amet ledger lorem dolor step2: - title: You alone have initialized your recovery phrase + title: Did you save your recovery phrase by yourself? desc: This is a long text, please replace it with the final wording once it’s done. Lorem ipsum dolor amet ledger lorem dolor step3: - title: Your device is a genuine Ledger device + title: Check if your Ledger device is genuine desc: This is a long text, please replace it with the final wording once it’s done. Lorem ipsum dolor amet ledger lorem dolor buttons: genuineCheck: Genuine check + tryAgain: Check again contactSupport: Contact Support errorPage: ledgerNano: title: Something is wrong with your Ledger Nano S - desc: Your Ledger Nano S should now display Your device is now ready. Before getting started, please confirm that + desc: A problem occurred with your Ledger Nano S. Contact Ledger Support to get assistance or go back to the security check. + ledgerBlue: + title: Something is wrong with your Ledger Blue + desc: A problem occurred with your Ledger Blue. Contact Ledger Support to get assistance or go back to the security check. setPassword: - title: This is the title of the screen. 1 line is the maximum - desc: This is a long text, please replace it with the final wording once it’s done. Lorem ipsum dolor amet ledger lorem dolor ipsum amet + title: Choose a password to securely access Ledger Live + desc: Use uppercase, lowercase, special characters (#, @, !, ?) and numbers for a stronger password. analytics: - title: This is the title of the screen. 1 line is the maximum + title: Help Ledger to improve its products and services desc: This is a long text, please replace it with the final wording once it’s done.
Lorem ipsum dolor amet ledger lorem dolor ipsum amet + shareDiagnostics: + title: Share analytics + desc: Help Ledger improve its products and services by automatically sending diagnostics and usage data. + shareData: + title: Share analytics + desc: Help Ledger improve its products and services by automatically sending diagnostics and usage data. finish: title: This is the title of the screen. 1 line is the maximum desc: This is a long text, please replace it with the final wording once it’s done.
Lorem ipsum dolor amet ledger lorem dolor ipsum amet