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) {
const { onboarding, t } = props
const { stepName, genuine } = onboarding
const { stepName, genuine, onboardingRelaunched } = onboarding
const isInitializedFlow = onboarding.flowType === 'initializedDevice'
const regularFilteredSteps = onboarding.steps
const regularSteps = onboarding.steps
.filter(step => !step.external)
.map(step => ({ ...step, label: t(step.label) }))
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) }))
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 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
onboarding.flowType === 'initializedDevice' ? jumpStep('selectDevice') : prevStep()
}
handleNextStep = () => {
const { onboarding, jumpStep, nextStep } = this.props
onboarding.onboardingRelaunched ? jumpStep('finish') : nextStep()
}
renderGenuineFail = () => (
<GenuineCheckErrorPage
redoGenuineCheck={this.redoGenuineCheck}
@ -280,7 +283,7 @@ class GenuineCheck extends PureComponent<StepProps, State> {
) : (
<OnboardingFooter
t={t}
nextStep={nextStep}
nextStep={this.handleNextStep}
prevStep={this.handlePrevStep}
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 ResetButton from '../ResetButton'
import AboutRowItem from '../AboutRowItem'
import LaunchOnboardingBtn from '../LaunchOnboardingBtn'
import {
SettingsSection as Section,
@ -57,6 +58,12 @@ class SectionHelp extends PureComponent<Props> {
>
<ExportLogsBtn />
</Row>
<Row
title={t('app:settings.profile.launchOnboarding')}
desc={t('app:settings.profile.launchOnboardingDesc')}
>
<LaunchOnboardingBtn />
</Row>
<Row
title={t('app:settings.openUserDataDirectory.title')}
desc={t('app:settings.openUserDataDirectory.desc')}

51
src/reducers/onboarding.js

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

3
static/i18n/en/app.yml

@ -7,6 +7,7 @@ common:
confirm: Confirm
cancel: Cancel
delete: Delete
launch: Launch
continue: Continue
learnMore: Learn more
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.
reportErrors: Report bugs
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:
desc: Information about Ledger Live, terms and conditions, and privacy policy.
help:

Loading…
Cancel
Save