Browse Source

Merge branch 'develop' into device-interaction

master
meriadec 7 years ago
parent
commit
7d079cd3dd
No known key found for this signature in database GPG Key ID: 1D2FC2305E2CB399
  1. 17
      PULL_REQUEST_TEMPLATE.md
  2. BIN
      build/windows/app.ico
  3. BIN
      build/windows/installerSidebar.bmp
  4. BIN
      build/windows/uninstaller.ico
  5. BIN
      build/windows/uninstallerSidebar.bmp
  6. 2
      electron-builder.yml
  7. 2
      scripts/compile.sh
  8. 2
      scripts/dist-dir.sh
  9. 2
      scripts/dist.sh
  10. 2
      scripts/hash-utils.sh
  11. 2
      scripts/install-ci-deps.sh
  12. 2
      scripts/postinstall.sh
  13. 2
      scripts/release.sh
  14. 2
      scripts/start.sh
  15. 7
      src/analytics/Track.js
  16. 4
      src/analytics/TrackPage.js
  17. 4
      src/components/AccountPage/EmptyStateAccount.js
  18. 6
      src/components/AccountPage/index.js
  19. 4
      src/components/DashboardPage/index.js
  20. 2
      src/components/ExportLogsBtn.js
  21. 4
      src/components/ManagerPage/FlashMcu.js
  22. 22
      src/components/Onboarding/helperComponents.js
  23. 16
      src/components/Onboarding/steps/Finish.js
  24. 9
      src/components/Onboarding/steps/Init.js
  25. 11
      src/components/Onboarding/steps/NoDevice.js
  26. 14
      src/components/Onboarding/steps/SelectPIN/SelectPINblue.js
  27. 14
      src/components/Onboarding/steps/SelectPIN/SelectPINnano.js
  28. 14
      src/components/Onboarding/steps/SelectPIN/SelectPINrestoreBlue.js
  29. 18
      src/components/Onboarding/steps/SelectPIN/SelectPINrestoreNano.js
  30. 9
      src/components/Onboarding/steps/Start.js
  31. 19
      src/components/Onboarding/steps/WriteSeed/WriteSeedBlue.js
  32. 27
      src/components/Onboarding/steps/WriteSeed/WriteSeedNano.js
  33. 27
      src/components/Onboarding/steps/WriteSeed/WriteSeedRestore.js
  34. 8
      src/components/OperationsList/index.js
  35. 9
      src/components/SettingsPage/sections/Profile.js
  36. 3
      src/components/UpdateNotifier/UpdateDownloaded.js
  37. 16
      src/components/base/Button/index.js
  38. 18
      static/i18n/en/onboarding.yml

17
PULL_REQUEST_TEMPLATE.md

@ -0,0 +1,17 @@
## What is the type of this PR?
<!-- e.g. Bug Fix, Feature, Code Quality Improvement, UI Polish... -->
## Any background context and/or relevant tickets/issues you want to provide with?
<!-- e.g. GitHub issue #45 -->
## Short description on what this PR suppose to do?
<!-- e.g. Adding genuine check to the onboarding -->
## Any special conditions required for testing?
<!-- e.g. Clear db, add special env variable.. -->
## Screenshots (if appropriate)

BIN
build/windows/app.ico

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 KiB

BIN
build/windows/installerSidebar.bmp

Binary file not shown.

Before

Width:  |  Height:  |  Size: 201 KiB

After

Width:  |  Height:  |  Size: 151 KiB

BIN
build/windows/uninstaller.ico

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 KiB

BIN
build/windows/uninstallerSidebar.bmp

Binary file not shown.

Before

Width:  |  Height:  |  Size: 201 KiB

After

Width:  |  Height:  |  Size: 151 KiB

2
electron-builder.yml

@ -27,6 +27,7 @@ linux:
win:
artifactName: ${name}-${version}-${os}-${arch}.${ext}
icon: build/windows/app.ico
certificateSubjectName: Ledger SAS
certificateSha1: 7dd9acb2ef0402883c65901ebbafd06e5293d391
signingHashAlgorithms:
@ -45,6 +46,7 @@ nsis:
allowToChangeInstallationDirectory: true
installerIcon: build/windows/installer.ico
installerSidebar: build/windows/installerSidebar.bmp
uninstallerIcon: build/windows/uninstaller.ico
uninstallerSidebar: build/windows/uninstallerSidebar.bmp
files:

2
scripts/compile.sh

@ -1,4 +1,4 @@
#/bin/bash
#!/bin/bash
set -e

2
scripts/dist-dir.sh

@ -1,3 +1,3 @@
#/bin/bash
#!/bin/bash
yarn compile && DEBUG=electron-builder electron-builder --dir -c.compression=store -c.mac.identity=null

2
scripts/dist.sh

@ -1,3 +1,3 @@
#/bin/bash
#!/bin/bash
yarn compile && DEBUG=electron-builder electron-builder

2
scripts/hash-utils.sh

@ -1,4 +1,4 @@
#/bin/bash
#!/bin/bash
function GET_HASH_PATH {
HASH_NAME=$1

2
scripts/install-ci-deps.sh

@ -1,4 +1,4 @@
#/bin/bash
#!/bin/bash
source scripts/hash-utils.sh

2
scripts/postinstall.sh

@ -1,4 +1,4 @@
#/bin/bash
#!/bin/bash
source scripts/hash-utils.sh

2
scripts/release.sh

@ -21,4 +21,4 @@ fi
# TODO check if local git HEAD is EXACTLY our remote master HEAD
yarn compile
build
DEBUG=electron-builder yarn run electron-builder build --publish always

2
scripts/start.sh

@ -1,4 +1,4 @@
#/bin/bash
#!/bin/bash
concurrently --raw --kill-others \
"cross-env NODE_ENV=development webpack-cli --mode development --watch --config webpack/internals.config.js" \

7
src/analytics/Track.js

@ -1,3 +1,4 @@
import logger from 'logger'
import { PureComponent } from 'react'
import { track } from './segment'
@ -6,9 +7,11 @@ class Track extends PureComponent<{
onUnmount?: boolean,
onUpdate?: boolean,
event: string,
properties?: Object,
}> {
componentDidMount() {
if (typeof this.props.event !== 'string') {
logger.warn('analytics Track: invalid event=', this.props.event)
}
if (this.props.onMount) this.track()
}
componentDidUpdate() {
@ -18,7 +21,7 @@ class Track extends PureComponent<{
if (this.props.onUnmount) this.track()
}
track = () => {
const { event, properties } = this.props
const { event, onMount, onUnmount, onUpdate, ...properties } = this.props
track(event, properties)
}
render() {

4
src/analytics/TrackPage.js

@ -1,9 +1,9 @@
import { PureComponent } from 'react'
import { page } from './segment'
class TrackPage extends PureComponent<{ category: string, name?: string, properties?: Object }> {
class TrackPage extends PureComponent<{ category: string, name?: string }> {
componentDidMount() {
const { category, name, properties } = this.props
const { category, name, ...properties } = this.props
page(category, name, properties)
}
render() {

4
src/components/AccountPage/EmptyStateAccount.js

@ -43,11 +43,11 @@ class EmptyStateAccount extends PureComponent<Props, *> {
<Title>{t('app:account.emptyState.title')}</Title>
<Description>
<Trans i18nKey="app:account.emptyState.desc">
Make sure the
{'Make sure the'}
<Text ff="Open Sans|SemiBold" color="dark">
{account.currency.name}
</Text>
app is installed to receive funds.
{'app is installed to receive funds.'}
</Trans>
</Description>
<Button mt={3} padded primary onClick={() => openModal(MODAL_RECEIVE, { account })}>

6
src/components/AccountPage/index.js

@ -109,10 +109,8 @@ class AccountPage extends PureComponent<Props> {
<Box key={account.id}>
<TrackPage
category="Account"
properties={{
currency: account.currency.id,
operationsLength: account.operations.length,
}}
currency={account.currency.id}
operationsLength={account.operations.length}
/>
<SyncOneAccountOnMount priority={10} accountId={account.id} />
<Box horizontal mb={5} flow={4}>

4
src/components/DashboardPage/index.js

@ -104,7 +104,9 @@ class DashboardPage extends PureComponent<Props> {
<UpdateNotifier />
<TrackPage
category="Portfolio"
properties={{ totalAccounts, totalOperations, totalCurrencies }}
totalAccounts={totalAccounts}
totalOperations={totalOperations}
totalCurrencies={totalCurrencies}
/>
<Box flow={7}>
{totalAccounts > 0 ? (

2
src/components/ExportLogsBtn.js

@ -71,7 +71,7 @@ class ExportLogsBtn extends Component<{
return hookToShortcut ? (
<KeyHandler keyValue="e" onKeyHandle={this.onKeyHandle} />
) : (
<Button primary onClick={this.handleExportLogs}>
<Button primary event="ExportLogs" onClick={this.handleExportLogs}>
{t('app:settings.exportLogs.btn')}
</Button>
)

4
src/components/ManagerPage/FlashMcu.js

@ -40,8 +40,8 @@ class FlashMcu extends PureComponent<Props, State> {
render() {
return (
<div>
<h1>Flashing MCU</h1>
<button onClick={this.flashMCU}>flash</button>
<h1>{'Flashing MCU'}</h1>
<button onClick={this.flashMCU}>{'flash'}</button>
</div>
)
}

22
src/components/Onboarding/helperComponents.js

@ -52,17 +52,31 @@ export const OnboardingFooterWrapper = styled(Box).attrs({
border-bottom-left-radius: ${radii[1]}px;
border-bottom-right-radius: ${radii[1]}px;
`
// LIVE LOGO
export function LiveLogo({ icon, ...p }: { icon: any }) {
return <LiveLogoContainer {...p}>{icon}</LiveLogoContainer>
}
export const LiveLogoContainer = styled(Box).attrs({
borderRadius: '50%',
alignItems: 'center',
justifyContent: 'center',
})`
box-shadow: 0 2px 24px 0 #00000014;
width: ${p => (p.width ? p.width : 80)}
height: ${p => (p.height ? p.height : 80)}
`
// INSTRUCTION LIST
type StepType = {
icon: any,
desc: string,
desc: any,
}
export function OptionRow({ step }: { step: StepType }) {
export function OptionRow({ step, ...p }: { step: StepType }) {
const { icon, desc } = step
return (
<Box horizontal m="7px" style={{ minWidth: 420 }}>
<Box justify="center">{icon}</Box>
<Box {...p}>{icon}</Box>
<Box justify="center" shrink>
<OptionRowDesc>{desc}</OptionRowDesc>
</Box>
@ -91,7 +105,7 @@ export function DisclaimerBox({ disclaimerNotes, ...p }: { disclaimerNotes: any
<DisclaimerBoxIconContainer>
<IconSensitiveOperationShield />
</DisclaimerBoxIconContainer>
{disclaimerNotes.map(note => <OptionRow key={note.key} step={note} />)}
{disclaimerNotes.map(note => <OptionRow justify="center" key={note.key} step={note} />)}
</Box>
</DisclaimerBoxContainer>
)

16
src/components/Onboarding/steps/Finish.js

@ -3,18 +3,19 @@
import React from 'react'
import { shell } from 'electron'
import styled from 'styled-components'
import { i } from 'helpers/staticPath'
import Box from 'components/base/Box'
import Button from 'components/base/Button'
import ConfettiParty from 'components/ConfettiParty'
import IconCheckCircle from 'icons/CheckCircle'
import IconCheckFull from 'icons/CheckFull'
import IconSocialTwitter from 'icons/Twitter'
import IconSocialReddit from 'icons/Reddit'
import IconSocialGithub from 'icons/Github'
import type { StepProps } from '..'
import { Title, Description } from '../helperComponents'
import { Title, Description, LiveLogo } from '../helperComponents'
const ConfettiLayer = styled.div`
position: absolute;
@ -55,9 +56,16 @@ export default (props: StepProps) => {
<ConfettiParty />
</ConfettiLayer>
<Box alignItems="center">
<Box color="positiveGreen">
<IconCheckCircle size={44} />
<Box style={{ position: 'relative' }}>
<LiveLogo
style={{ width: 64, height: 64 }}
icon={<img alt="" src={i('ledgerlive-logo.svg')} width={40} height={40} />}
/>
<Box color="positiveGreen" style={{ position: 'absolute', right: 0, bottom: 0 }}>
<IconCheckFull size={18} />
</Box>
</Box>
<Box pt={5} align="center">
<Title>{t('onboarding:finish.title')}</Title>
<Description>{t('onboarding:finish.desc')}</Description>

9
src/components/Onboarding/steps/Init.js

@ -13,7 +13,7 @@ import IconCheck from 'icons/Check'
import IconExternalLink from 'icons/ExternalLink'
import IconChevronRight from 'icons/ChevronRight'
import { i } from 'helpers/staticPath'
import { Title } from '../helperComponents'
import { Title, LiveLogo } from '../helperComponents'
import type { StepProps } from '..'
@ -65,9 +65,10 @@ class Init extends PureComponent<StepProps, *> {
return (
<Box sticky justifyContent="center">
<Box align="center">
<Box color="wallet">
<img alt="" src={i('ledgerlive-logo.svg')} width={50} height={50} />
</Box>
<LiveLogo
style={{ width: 64, height: 64 }}
icon={<img src={i('ledgerlive-logo.svg')} alt="" width={40} height={40} />}
/>
<Box m={5} style={{ maxWidth: 480 }}>
<Title>{t('onboarding:init.title')}</Title>
</Box>

11
src/components/Onboarding/steps/NoDevice.js

@ -2,14 +2,14 @@
import React, { PureComponent } from 'react'
import { shell } from 'electron'
import { i } from 'helpers/staticPath'
import Box from 'components/base/Box'
import IconUser from 'icons/User'
import IconCart from 'icons/Cart'
import IconTruck from 'icons/Truck'
import IconInfoCircle from 'icons/InfoCircle'
import Button from '../../base/Button/index'
import { Title, OnboardingFooterWrapper } from '../helperComponents'
import { Title, OnboardingFooterWrapper, LiveLogo } from '../helperComponents'
import { OptionFlowCard } from './Init'
import type { StepProps } from '..'
@ -48,9 +48,10 @@ class NoDevice extends PureComponent<StepProps, *> {
return (
<Box sticky pt={130}>
<Box grow alignItems="center">
<Box color="wallet">
<IconUser size={36} />
</Box>
<LiveLogo
style={{ width: 64, height: 64 }}
icon={<img src={i('ledgerlive-logo.svg')} alt="" width={40} height={40} />}
/>
<Box m={5} style={{ maxWidth: 480 }}>
<Title>{t('onboarding:noDevice.title')}</Title>
</Box>

14
src/components/Onboarding/steps/SelectPIN/SelectPINblue.js

@ -1,10 +1,11 @@
// @flow
import React, { PureComponent } from 'react'
import { translate } from 'react-i18next'
import { translate, Trans } from 'react-i18next'
import { colors } from 'styles/theme'
import { i } from 'helpers/staticPath'
import Box from 'components/base/Box'
import Text from 'components/base/Text'
import type { T } from 'types/common'
@ -29,7 +30,16 @@ class SelectPIN extends PureComponent<Props, *> {
{
key: 'step2',
icon: <IconOptionRow>{'2.'}</IconOptionRow>,
desc: t('onboarding:selectPIN.initialize.instructions.blue.step2'),
desc: (
<Box style={{ display: 'block' }}>
<Trans i18nKey="onboarding:selectPIN.initialize.instructions.blue.step2">
{'Tap on'}
<Text ff="Open Sans|SemiBold" color="dark">
{'Configure as new device'}
</Text>
</Trans>
</Box>
),
},
{
key: 'step3',

14
src/components/Onboarding/steps/SelectPIN/SelectPINnano.js

@ -1,10 +1,11 @@
// @flow
import React, { PureComponent } from 'react'
import { translate } from 'react-i18next'
import { translate, Trans } from 'react-i18next'
import { colors } from 'styles/theme'
import { i } from 'helpers/staticPath'
import Box from 'components/base/Box'
import Text from 'components/base/Text'
import type { T } from 'types/common'
@ -34,7 +35,16 @@ class SelectPINnano extends PureComponent<Props, *> {
{
key: 'step3',
icon: <IconOptionRow>{'3.'}</IconOptionRow>,
desc: t('onboarding:selectPIN.initialize.instructions.nano.step3'),
desc: (
<Box style={{ display: 'block' }}>
<Trans i18nKey="onboarding:selectPIN.initialize.instructions.nano.step3">
{'Press the right button to select'}
<Text ff="Open Sans|SemiBold" color="dark">
{'Configure as new device'}
</Text>
</Trans>
</Box>
),
},
{
key: 'step4',

14
src/components/Onboarding/steps/SelectPIN/SelectPINrestoreBlue.js

@ -1,10 +1,11 @@
// @flow
import React, { PureComponent } from 'react'
import { translate } from 'react-i18next'
import { translate, Trans } from 'react-i18next'
import { colors } from 'styles/theme'
import { i } from 'helpers/staticPath'
import Box from 'components/base/Box'
import Text from 'components/base/Text'
import type { T } from 'types/common'
@ -29,7 +30,16 @@ class SelectPINrestoreBlue extends PureComponent<Props, *> {
{
key: 'step2',
icon: <IconOptionRow>{'2.'}</IconOptionRow>,
desc: t('onboarding:selectPIN.restore.instructions.blue.step2'),
desc: (
<Box style={{ display: 'block' }}>
<Trans i18nKey="onboarding:selectPIN.restore.instructions.blue.step2">
{'Tap on'}
<Text ff="Open Sans|SemiBold" color="dark">
{'Restore configuration'}
</Text>
</Trans>
</Box>
),
},
{
key: 'step3',

18
src/components/Onboarding/steps/SelectPIN/SelectPINrestoreNano.js

@ -1,10 +1,11 @@
// @flow
import React, { PureComponent } from 'react'
import { translate } from 'react-i18next'
import { translate, Trans } from 'react-i18next'
import { colors } from 'styles/theme'
import { i } from 'helpers/staticPath'
import Box from 'components/base/Box'
import Text from 'components/base/Text'
import type { T } from 'types/common'
@ -34,7 +35,20 @@ class SelectPINrestoreNano extends PureComponent<Props, *> {
{
key: 'step3',
icon: <IconOptionRow>{'3.'}</IconOptionRow>,
desc: t('onboarding:selectPIN.restore.instructions.nano.step3'),
desc: (
<Box style={{ display: 'block' }}>
<Trans i18nKey="onboarding:selectPIN.restore.instructions.nano.step3">
{'Press the left button to cancel'}
<Text ff="Open Sans|SemiBold" color="dark">
{'Initialize as new device?'}
</Text>
{'Press the right button to select'}
<Text ff="Open Sans|SemiBold" color="dark">
{'Restore configuration?'}
</Text>
</Trans>
</Box>
),
},
{
key: 'step4',

9
src/components/Onboarding/steps/Start.js

@ -7,15 +7,18 @@ import Box from 'components/base/Box'
import Button from 'components/base/Button'
import type { StepProps } from '..'
import { Title } from '../helperComponents'
import { Title, LiveLogo } from '../helperComponents'
export default (props: StepProps) => {
const { jumpStep, t } = props
return (
<Box sticky justifyContent="center">
<Box alignItems="center">
<img alt="" src={i('get-started-onb.svg')} />
<Box my={4}>
<LiveLogo
style={{ width: 80, height: 80 }}
icon={<img src={i('ledgerlive-logo.svg')} alt="" width={50} height={50} />}
/>
<Box my={5}>
<Title>{t('onboarding:start.title')}</Title>
</Box>
<Button padded primary onClick={() => jumpStep('init')}>

19
src/components/Onboarding/steps/WriteSeed/WriteSeedBlue.js

@ -1,12 +1,13 @@
// @flow
import React, { PureComponent, Fragment } from 'react'
import { translate } from 'react-i18next'
import { translate, Trans } from 'react-i18next'
import { colors } from 'styles/theme'
import { i } from 'helpers/staticPath'
import type { T } from 'types/common'
import Box from 'components/base/Box'
import Text from 'components/base/Text'
import IconChevronRight from 'icons/ChevronRight'
import {
@ -35,7 +36,21 @@ class WriteSeedBlue extends PureComponent<Props, *> {
{
key: 'step2',
icon: <IconOptionRow>{'2.'}</IconOptionRow>,
desc: t('onboarding:writeSeed.initialize.blue.step2'),
desc: (
<Box style={{ display: 'block' }}>
<Trans i18nKey="onboarding:writeSeed.initialize.blue.step2">
{'Tap'}
<Text ff="Open Sans|SemiBold" color="dark">
{'Next'}
</Text>
{'to move to the next words. Repeat the process until the'}
<Text ff="Open Sans|SemiBold" color="dark">
{'Confirmation'}
</Text>
{'screen appears.'}
</Trans>
</Box>
),
},
{
key: 'step3',

27
src/components/Onboarding/steps/WriteSeed/WriteSeedNano.js

@ -1,12 +1,13 @@
// @flow
import React, { PureComponent, Fragment } from 'react'
import { translate } from 'react-i18next'
import { translate, Trans } from 'react-i18next'
import { colors } from 'styles/theme'
import { i } from 'helpers/staticPath'
import type { T } from 'types/common'
import Box from 'components/base/Box'
import Text from 'components/base/Text'
import IconChevronRight from 'icons/ChevronRight'
import {
@ -30,12 +31,32 @@ class WriteSeedNano extends PureComponent<Props, *> {
{
key: 'step1',
icon: <IconOptionRow>{'1.'}</IconOptionRow>,
desc: t('onboarding:writeSeed.initialize.nano.step1'),
desc: (
<Box style={{ display: 'block' }}>
<Trans i18nKey="onboarding:writeSeed.initialize.nano.step1">
{'Copy the word displayed below'}
<Text ff="Open Sans|SemiBold" color="dark">
{'Word #1'}
</Text>
{'in position 1 on a blank Recovery sheet.'}
</Trans>
</Box>
),
},
{
key: 'step2',
icon: <IconOptionRow>{'2.'}</IconOptionRow>,
desc: t('onboarding:writeSeed.initialize.nano.step2'),
desc: (
<Box style={{ display: 'block' }}>
<Trans i18nKey="onboarding:writeSeed.initialize.nano.step2">
{'Press the right button to display'}
<Text ff="Open Sans|SemiBold" color="dark">
{'Word #2'}
</Text>
{'and repeat the process until all 24 words are copied on the Recovery sheet.'}
</Trans>
</Box>
),
},
{
key: 'step3',

27
src/components/Onboarding/steps/WriteSeed/WriteSeedRestore.js

@ -1,10 +1,11 @@
// @flow
import React, { PureComponent, Fragment } from 'react'
import { translate } from 'react-i18next'
import { translate, Trans } from 'react-i18next'
import { colors } from 'styles/theme'
import { i } from 'helpers/staticPath'
import Box from 'components/base/Box'
import Text from 'components/base/Text'
import type { T } from 'types/common'
import type { OnboardingState } from 'reducers/onboarding'
@ -38,12 +39,32 @@ class WriteSeedRestore extends PureComponent<Props, *> {
{
key: 'step2',
icon: <IconOptionRow>{'2.'}</IconOptionRow>,
desc: t('onboarding:writeSeed.restore.nano.step2'),
desc: (
<Box style={{ display: 'block' }}>
<Trans i18nKey="onboarding:writeSeed.restore.nano.step2">
{'Select the first letters of'}
<Text ff="Open Sans|SemiBold" color="dark">
{'Word #1'}
</Text>
{'by pressing the right or left button. Press both buttons to confirm each letter.'}
</Trans>
</Box>
),
},
{
key: 'step3',
icon: <IconOptionRow>{'3.'}</IconOptionRow>,
desc: t('onboarding:writeSeed.restore.nano.step3'),
desc: (
<Box style={{ display: 'block' }}>
<Trans i18nKey="onboarding:writeSeed.restore.nano.step3">
{'Select'}
<Text ff="Open Sans|SemiBold" color="dark">
{'Word #1'}
</Text>
{'from the suggested words. Press both buttons to continue.'}
</Trans>
</Box>
),
},
{
key: 'step4',

8
src/components/OperationsList/index.js

@ -134,13 +134,11 @@ export class OperationsList extends PureComponent<Props, State> {
<Track
onMount
event="OperationsListEndReached"
properties={{
totalSections: groupedOperations.sections.length,
totalOperations: groupedOperations.sections.reduce(
totalSections={groupedOperations.sections.length}
totalOperations={groupedOperations.sections.reduce(
(sum, s) => sum + s.data.length,
0,
),
}}
)}
/>
) : null}
{!groupedOperations.completed ? (

9
src/components/SettingsPage/sections/Profile.js

@ -15,6 +15,7 @@ import hardReset from 'helpers/hardReset'
import type { SettingsState } from 'reducers/settings'
import type { T } from 'types/common'
import Track from 'analytics/Track'
import TrackPage from 'analytics/TrackPage'
import ExportLogsBtn from 'components/ExportLogsBtn'
import CheckBox from 'components/base/CheckBox'
@ -157,6 +158,7 @@ class TabProfile extends PureComponent<Props, State> {
title={t('app:settings.profile.password')}
desc={t('app:settings.profile.passwordDesc')}
>
<Track onUpdate event={isPasswordEnabled ? 'PasswordEnabled' : 'PasswordDisabled'} />
<Box horizontal flow={2} align="center">
{isPasswordEnabled && (
<Button onClick={this.handleOpenPasswordModal}>
@ -170,6 +172,7 @@ class TabProfile extends PureComponent<Props, State> {
title={t('app:settings.profile.developerMode')}
desc={t('app:settings.profile.developerModeDesc')}
>
<Track onUpdate event={settings.developerMode ? 'DevModeEnabled' : 'DevModeDisabled'} />
<CheckBox
isChecked={settings.developerMode}
onChange={developerMode => saveSettings({ developerMode })}
@ -179,6 +182,7 @@ class TabProfile extends PureComponent<Props, State> {
title={t('app:settings.profile.reportErrors')}
desc={t('app:settings.profile.reportErrorsDesc')}
>
<Track onUpdate event={settings.sentryLogs ? 'SentryEnabled' : 'SentryDisabled'} />
<CheckBox
isChecked={settings.sentryLogs}
onChange={sentryLogs => saveSettings({ sentryLogs })}
@ -188,6 +192,7 @@ class TabProfile extends PureComponent<Props, State> {
title={t('app:settings.profile.analytics')}
desc={t('app:settings.profile.analyticsDesc')}
>
<Track onUpdate event={settings.sentryLogs ? 'SentryEnabled' : 'SentryDisabled'} />
<CheckBox
isChecked={settings.shareAnalytics}
onChange={shareAnalytics => saveSettings({ shareAnalytics })}
@ -197,7 +202,7 @@ class TabProfile extends PureComponent<Props, State> {
title={t('app:settings.profile.softResetTitle')}
desc={t('app:settings.profile.softResetDesc')}
>
<Button primary onClick={this.handleOpenSoftResetModal}>
<Button primary onClick={this.handleOpenSoftResetModal} event="ClearCacheIntent">
{t('app:settings.profile.softReset')}
</Button>
</Row>
@ -205,7 +210,7 @@ class TabProfile extends PureComponent<Props, State> {
title={t('app:settings.profile.hardResetTitle')}
desc={t('app:settings.profile.hardResetDesc')}
>
<Button danger onClick={this.handleOpenHardResetModal}>
<Button danger onClick={this.handleOpenHardResetModal} event="HardResetIntent">
{t('app:settings.profile.hardReset')}
</Button>
</Row>

3
src/components/UpdateNotifier/UpdateDownloaded.js

@ -35,7 +35,8 @@ const Container = styled(Box).attrs({
px: 3,
bg: 'wallet',
color: 'white',
mt: '-35px',
mt: '-50px',
mb: '35px',
style: p => ({
transform: `translate3d(0, ${p.offset}%, 0)`,
}),

16
src/components/base/Button/index.js

@ -4,6 +4,7 @@ import React from 'react'
import styled from 'styled-components'
import { space, fontSize, fontWeight, color } from 'styled-system'
import noop from 'lodash/noop'
import { track } from 'analytics/segment'
import { darken, lighten, rgba } from 'styles/helpers'
import fontFamily from 'styles/styled/fontFamily'
@ -171,13 +172,24 @@ type Props = {
small?: boolean,
padded?: boolean,
isLoading?: boolean,
event?: string,
eventProperties?: Object,
}
const Button = (props: Props) => {
const { onClick, children, disabled, isLoading } = props
const { disabled } = props
const { onClick, children, isLoading, event, eventProperties, ...rest } = props
const isClickDisabled = disabled || isLoading
const onClickHandler = e => {
if (onClick) {
if (event) {
track(event, eventProperties)
}
onClick(e)
}
}
return (
<Base {...props} onClick={isClickDisabled ? undefined : onClick}>
<Base {...rest} onClick={isClickDisabled ? undefined : onClickHandler}>
{isLoading ? <Spinner size={16} /> : children}
</Base>
)

18
static/i18n/en/onboarding.yml

@ -44,11 +44,11 @@ selectPIN:
nano:
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?. # <bold>Configure as new device?<bold>.
step3: Press the right button to select <1><0>Configure as new device?</0></1>
step4: 'Choose a PIN code between 4 and 8 digits long, followed by the checkmark (✓).'
blue:
step1: Connect the Ledger Blue to your computer.
step2: Tap on Configure as new device.
step2: Tap on <1><0>Configure as new device.</0></1>
step3: Choose a PIN code between 4 and 8 digits long.
restore:
title: Choose your PIN code
@ -56,31 +56,31 @@ selectPIN:
nano:
step1: Connect the Ledger Nano S to your computer.
step2: Press both buttons simultaneously as instructed on the screen.
step3: Press the left button to cancel Initialize as new device?. Press the right button to select Restore configuration?. # <bold>Initialize as new device?</bold> <bold>Restore configuration?</bold>.
step3: Press the left button to cancel <1><0>Initialize as new device?</0></1> Press the right button to select <3><0>Restore configuration?</0></3>
step4: 'Choose a PIN code between 4 and 8 digits long followed by the checkmark (✓).'
blue:
step1: Connect the Ledger Blue to your computer.
step2: Tap on Restore configuration. # <bold>Restore configuration</bold>.
step2: Tap on <1><0>Restore configuration</0></1>.
step3: Choose a PIN code between 4 and 8 digits long.
writeSeed:
initialize:
title: Save your recovery phrase
desc: Your device will generate a recovery phrase of 24 words, displayed only once.
nano:
step1: 'Copy the word displayed below Word #1 in position 1 on a blank Recovery sheet.' # <bold>Word #1</bold> <italic>Recovery sheet</italic>
step2: 'Press the right button to display Word #2 and repeat the process until all 24 words are copied on the Recovery sheet.' # <bold>Word #2</bold> <italic>Recovery sheet</italic>
step1: 'Copy the word displayed below <1><0>Word #1</0></1> in position 1 on a blank Recovery sheet.'
step2: 'Press the right button to display <1><0>Word #2</0></1> and repeat the process until all 24 words are copied on the Recovery sheet.' #<italic>Recovery sheet</italic>
step3: 'Confirm your recovery phrase: select each requested word and press both buttons to validate it.'
blue:
step1: Copy each word of the recovery phrase on a blank Recovery sheet. Copy the words in the same order. # <i>Recovery sheet</i>
step2: Tap Next to move to the next words. Repeat the process until the Confirmation screen appears. # <bold>Next</bold> <bold>Confirmation</bold>
step2: Tap <1><0>Next</0></1> to move to the next words. Repeat the process until the <3><0>Confirmation</0></3> screen appears.
step3: Type each requested word to confirm your recovery phrase.
restore:
title: Enter your recovery phrase
desc: Copy the 24-word recovery phrase from your Recovery sheet on your device.
nano:
step1: Select the length of your recovery phrase. Press both buttons to continue.
step2: 'Select the first letters of Word #1 by pressing the right or left button. Press both buttons to confirm each letter.' # <bold>Word #1</bold>
step3: 'Select Word #1 from the suggested words. Press both buttons to continue.' # <bold>Word #1</bold>
step2: 'Select the first letters of <1><0>Word #1</0></1> by pressing the right or left button. Press both buttons to confirm each letter.'
step3: 'Select <1><0>Word #1</0></1> from the suggested words. Press both buttons to continue.'
step4: Repeat the process until the last word.
blue:
step1: Select the length of your recovery phrase.

Loading…
Cancel
Save