Browse Source

Fix/1055 (#1101)

be able to re-launch onboarding from the settings page
master
NastiaS 7 years ago
committed by Gaëtan Renaudeau
parent
commit
be14d8cbe0
  1. 21
      src/components/Onboarding/OnboardingBreadcrumb.js
  2. 7
      src/components/Onboarding/steps/GenuineCheck/index.js
  3. 50
      src/components/SettingsPage/LaunchOnboardingBtn.js
  4. 7
      src/components/SettingsPage/sections/Help.js
  5. 51
      src/reducers/onboarding.js
  6. 3
      static/i18n/en/app.yml

21
src/components/Onboarding/OnboardingBreadcrumb.js

@ -20,18 +20,31 @@ type Props = {
function OnboardingBreadcrumb(props: Props) { function OnboardingBreadcrumb(props: Props) {
const { onboarding, t } = props const { onboarding, t } = props
const { stepName, genuine } = onboarding const { stepName, genuine, onboardingRelaunched } = onboarding
const isInitializedFlow = onboarding.flowType === 'initializedDevice' const isInitializedFlow = onboarding.flowType === 'initializedDevice'
const regularFilteredSteps = onboarding.steps const regularSteps = onboarding.steps
.filter(step => !step.external) .filter(step => !step.external)
.map(step => ({ ...step, label: t(step.label) })) .map(step => ({ ...step, label: t(step.label) }))
const alreadyInitializedSteps = onboarding.steps const alreadyInitializedSteps = onboarding.steps
.filter(step => !step.external && step.name !== 'writeSeed' && step.name !== 'selectPIN') .filter(step => !step.external && !step.options.alreadyInitSkip)
.map(step => ({ ...step, label: t(step.label) })) .map(step => ({ ...step, label: t(step.label) }))
const filteredSteps = isInitializedFlow ? alreadyInitializedSteps : regularFilteredSteps const onboardingRelaunchedSteps = onboarding.steps
.filter(
step =>
isInitializedFlow
? !step.options.alreadyInitSkip && !step.external && !step.options.relaunchSkip
: !step.external && !step.options.relaunchSkip,
)
.map(step => ({ ...step, label: t(step.label) }))
const filteredSteps = onboardingRelaunched
? onboardingRelaunchedSteps
: isInitializedFlow
? alreadyInitializedSteps
: regularSteps
const stepIndex = findIndex(filteredSteps, s => s.name === stepName) const stepIndex = findIndex(filteredSteps, s => s.name === stepName)
const genuineStepIndex = findIndex(filteredSteps, s => s.name === 'genuineCheck') const genuineStepIndex = findIndex(filteredSteps, s => s.name === 'genuineCheck')

7
src/components/Onboarding/steps/GenuineCheck/index.js

@ -151,7 +151,10 @@ class GenuineCheck extends PureComponent<StepProps, State> {
const { prevStep, onboarding, jumpStep } = this.props const { prevStep, onboarding, jumpStep } = this.props
onboarding.flowType === 'initializedDevice' ? jumpStep('selectDevice') : prevStep() onboarding.flowType === 'initializedDevice' ? jumpStep('selectDevice') : prevStep()
} }
handleNextStep = () => {
const { onboarding, jumpStep, nextStep } = this.props
onboarding.onboardingRelaunched ? jumpStep('finish') : nextStep()
}
renderGenuineFail = () => ( renderGenuineFail = () => (
<GenuineCheckErrorPage <GenuineCheckErrorPage
redoGenuineCheck={this.redoGenuineCheck} redoGenuineCheck={this.redoGenuineCheck}
@ -280,7 +283,7 @@ class GenuineCheck extends PureComponent<StepProps, State> {
) : ( ) : (
<OnboardingFooter <OnboardingFooter
t={t} t={t}
nextStep={nextStep} nextStep={this.handleNextStep}
prevStep={this.handlePrevStep} prevStep={this.handlePrevStep}
isContinueDisabled={!genuine.isDeviceGenuine} isContinueDisabled={!genuine.isDeviceGenuine}
/> />

50
src/components/SettingsPage/LaunchOnboardingBtn.js

@ -0,0 +1,50 @@
// @flow
import React, { Fragment, PureComponent } from 'react'
import { connect } from 'react-redux'
import { saveSettings } from 'actions/settings'
import { translate } from 'react-i18next'
import type { T } from 'types/common'
import type { SettingsState } from 'reducers/settings'
import type { OnboardingState } from 'reducers/onboarding'
import Track from 'analytics/Track'
import Onboarding from 'components/Onboarding'
import Button from 'components/base/Button/index'
import { relaunchOnboarding } from 'reducers/onboarding'
const mapDispatchToProps = {
saveSettings,
relaunchOnboarding,
}
type Props = {
saveSettings: ($Shape<SettingsState>) => void,
relaunchOnboarding: ($Shape<OnboardingState>) => void,
t: T,
}
class LaunchOnboardingBtn extends PureComponent<Props> {
handleLaunchOnboarding = () => {
this.props.saveSettings({ hasCompletedOnboarding: false })
this.props.relaunchOnboarding({ onboardingRelaunched: true })
return <Onboarding />
}
render() {
const { t } = this.props
return (
<Fragment>
<Track onUpdate event={'Launch Onboarding from Settings'} />
<Button primary small onClick={this.handleLaunchOnboarding}>
{t('app:common.launch')}
</Button>
</Fragment>
)
}
}
export default translate()(
connect(
null,
mapDispatchToProps,
)(LaunchOnboardingBtn),
)

7
src/components/SettingsPage/sections/Help.js

@ -13,6 +13,7 @@ import OpenUserDataDirectoryBtn from 'components/OpenUserDataDirectoryBtn'
import CleanButton from '../CleanButton' import CleanButton from '../CleanButton'
import ResetButton from '../ResetButton' import ResetButton from '../ResetButton'
import AboutRowItem from '../AboutRowItem' import AboutRowItem from '../AboutRowItem'
import LaunchOnboardingBtn from '../LaunchOnboardingBtn'
import { import {
SettingsSection as Section, SettingsSection as Section,
@ -57,6 +58,12 @@ class SectionHelp extends PureComponent<Props> {
> >
<ExportLogsBtn /> <ExportLogsBtn />
</Row> </Row>
<Row
title={t('app:settings.profile.launchOnboarding')}
desc={t('app:settings.profile.launchOnboardingDesc')}
>
<LaunchOnboardingBtn />
</Row>
<Row <Row
title={t('app:settings.openUserDataDirectory.title')} title={t('app:settings.openUserDataDirectory.title')}
desc={t('app:settings.openUserDataDirectory.desc')} desc={t('app:settings.openUserDataDirectory.desc')}

51
src/reducers/onboarding.js

@ -8,9 +8,9 @@ type Step = {
external?: boolean, external?: boolean,
label?: string, label?: string,
options: { options: {
showFooter: boolean,
showBackground: boolean,
showBreadcrumb: boolean, showBreadcrumb: boolean,
relaunchSkip?: boolean,
alreadyInitSkip?: boolean,
}, },
} }
@ -28,10 +28,11 @@ export type OnboardingState = {
}, },
isLedgerNano: boolean | null, isLedgerNano: boolean | null,
flowType: string, flowType: string,
onboardingRelaunched?: boolean,
} }
const state: OnboardingState = { const initialState: OnboardingState = {
stepIndex: 0, // FIXME is this used at all? dup with stepName? stepIndex: 0,
stepName: SKIP_ONBOARDING ? 'analytics' : 'start', stepName: SKIP_ONBOARDING ? 'analytics' : 'start',
genuine: { genuine: {
pinStepPass: false, pinStepPass: false,
@ -43,13 +44,12 @@ const state: OnboardingState = {
}, },
isLedgerNano: null, isLedgerNano: null,
flowType: '', flowType: '',
onboardingRelaunched: false,
steps: [ steps: [
{ {
name: 'start', name: 'start',
external: true, external: true,
options: { options: {
showFooter: false,
showBackground: true,
showBreadcrumb: false, showBreadcrumb: false,
}, },
}, },
@ -57,8 +57,6 @@ const state: OnboardingState = {
name: 'init', name: 'init',
external: true, external: true,
options: { options: {
showFooter: false,
showBackground: true,
showBreadcrumb: false, showBreadcrumb: false,
}, },
}, },
@ -66,8 +64,6 @@ const state: OnboardingState = {
name: 'noDevice', name: 'noDevice',
external: true, external: true,
options: { options: {
showFooter: false,
showBackground: true,
showBreadcrumb: false, showBreadcrumb: false,
}, },
}, },
@ -75,8 +71,6 @@ const state: OnboardingState = {
name: 'selectDevice', name: 'selectDevice',
label: 'onboarding:breadcrumb.selectDevice', label: 'onboarding:breadcrumb.selectDevice',
options: { options: {
showFooter: false,
showBackground: true,
showBreadcrumb: true, showBreadcrumb: true,
}, },
}, },
@ -84,26 +78,22 @@ const state: OnboardingState = {
name: 'selectPIN', name: 'selectPIN',
label: 'onboarding:breadcrumb.selectPIN', label: 'onboarding:breadcrumb.selectPIN',
options: { options: {
showFooter: false,
showBackground: true,
showBreadcrumb: true, showBreadcrumb: true,
alreadyInitSkip: true,
}, },
}, },
{ {
name: 'writeSeed', name: 'writeSeed',
label: 'onboarding:breadcrumb.writeSeed', label: 'onboarding:breadcrumb.writeSeed',
options: { options: {
showFooter: false,
showBackground: true,
showBreadcrumb: true, showBreadcrumb: true,
alreadyInitSkip: true,
}, },
}, },
{ {
name: 'genuineCheck', name: 'genuineCheck',
label: 'onboarding:breadcrumb.genuineCheck', label: 'onboarding:breadcrumb.genuineCheck',
options: { options: {
showFooter: false,
showBackground: true,
showBreadcrumb: true, showBreadcrumb: true,
}, },
}, },
@ -111,26 +101,22 @@ const state: OnboardingState = {
name: 'setPassword', name: 'setPassword',
label: 'onboarding:breadcrumb.setPassword', label: 'onboarding:breadcrumb.setPassword',
options: { options: {
showFooter: false,
showBackground: true,
showBreadcrumb: true, showBreadcrumb: true,
relaunchSkip: true,
}, },
}, },
{ {
name: 'analytics', name: 'analytics',
label: 'onboarding:breadcrumb.analytics', label: 'onboarding:breadcrumb.analytics',
options: { options: {
showFooter: false,
showBackground: true,
showBreadcrumb: true, showBreadcrumb: true,
relaunchSkip: true,
}, },
}, },
{ {
name: 'finish', name: 'finish',
external: true, external: true,
options: { options: {
showFooter: false,
showBackground: true,
showBreadcrumb: false, showBreadcrumb: false,
}, },
}, },
@ -149,7 +135,7 @@ const handlers = {
} }
return { ...state, stepName: state.steps[index + 1].name, stepIndex: index + 1 } return { ...state, stepName: state.steps[index + 1].name, stepIndex: index + 1 }
}, },
ONBOARDING_PREV_STEP: state => { ONBOARDING_PREV_STEP: (state: OnboardingState) => {
const step = state.steps.find(step => step.name === state.stepName) const step = state.steps.find(step => step.name === state.stepName)
if (!step) { if (!step) {
return state return state
@ -160,7 +146,7 @@ const handlers = {
} }
return { ...state, stepName: state.steps[index - 1].name, stepIndex: index - 1 } return { ...state, stepName: state.steps[index - 1].name, stepIndex: index - 1 }
}, },
ONBOARDING_JUMP_STEP: (state, { payload: stepName }) => { ONBOARDING_JUMP_STEP: (state: OnboardingState, { payload: stepName }) => {
const step = state.steps.find(step => step.name === stepName) const step = state.steps.find(step => step.name === stepName)
if (!step) { if (!step) {
return state return state
@ -169,25 +155,30 @@ const handlers = {
return { ...state, stepName: step.name, stepIndex: index } return { ...state, stepName: step.name, stepIndex: index }
}, },
UPDATE_GENUINE_CHECK: (state, { payload: obj }) => ({ UPDATE_GENUINE_CHECK: (state: OnboardingState, { payload: obj }) => ({
...state, ...state,
genuine: { genuine: {
...state.genuine, ...state.genuine,
...obj, ...obj,
}, },
}), }),
ONBOARDING_SET_FLOW_TYPE: (state, { payload: flowType }) => ({ ONBOARDING_SET_FLOW_TYPE: (state: OnboardingState, { payload: flowType }) => ({
...state, ...state,
flowType, flowType,
}), }),
ONBOARDING_SET_DEVICE_TYPE: (state, { payload: isLedgerNano }) => ({ ONBOARDING_SET_DEVICE_TYPE: (state: OnboardingState, { payload: isLedgerNano }) => ({
...state, ...state,
isLedgerNano, isLedgerNano,
}), }),
ONBOARDING_RELAUNCH: (
state: OnboardingState,
{ payload: onboardingRelaunched }: { payload: $Shape<OnboardingState> },
) => ({ ...initialState, ...onboardingRelaunched }),
} }
export default handleActions(handlers, state) export default handleActions(handlers, initialState)
export const relaunchOnboarding = createAction('ONBOARDING_RELAUNCH')
export const nextStep = createAction('ONBOARDING_NEXT_STEP') export const nextStep = createAction('ONBOARDING_NEXT_STEP')
export const prevStep = createAction('ONBOARDING_PREV_STEP') export const prevStep = createAction('ONBOARDING_PREV_STEP')
export const jumpStep = createAction('ONBOARDING_JUMP_STEP') export const jumpStep = createAction('ONBOARDING_JUMP_STEP')

3
static/i18n/en/app.yml

@ -7,6 +7,7 @@ common:
confirm: Confirm confirm: Confirm
cancel: Cancel cancel: Cancel
delete: Delete delete: Delete
launch: Launch
continue: Continue continue: Continue
learnMore: Learn more learnMore: Learn more
skipThisStep: Skip this step skipThisStep: Skip this step
@ -359,6 +360,8 @@ settings:
analyticsDesc: Enable analytics of anonymous data to help Ledger improve the user experience. This includes the operating system, language, firmware versions and the number of added accounts. analyticsDesc: Enable analytics of anonymous data to help Ledger improve the user experience. This includes the operating system, language, firmware versions and the number of added accounts.
reportErrors: Report bugs reportErrors: Report bugs
reportErrorsDesc: Share anonymous usage and diagnostics data to help improve Ledger products, services and security features. reportErrorsDesc: Share anonymous usage and diagnostics data to help improve Ledger products, services and security features.
launchOnboarding: Onboarding
launchOnboardingDesc: Launch again the onboarding to add a new device to the Ledger Live application
about: about:
desc: Information about Ledger Live, terms and conditions, and privacy policy. desc: Information about Ledger Live, terms and conditions, and privacy policy.
help: help:

Loading…
Cancel
Save