14 changed files with 511 additions and 59 deletions
@ -0,0 +1,80 @@ |
|||||
|
// @flow
|
||||
|
/* eslint react/jsx-no-literals: 0 */ |
||||
|
|
||||
|
import React, { PureComponent, Fragment } from 'react' |
||||
|
import { translate, Trans } from 'react-i18next' |
||||
|
|
||||
|
import type { T } from 'types/common' |
||||
|
|
||||
|
import Modal, { ModalBody, ModalFooter, ModalTitle, ModalContent } from 'components/base/Modal' |
||||
|
import Text from 'components/base/Text' |
||||
|
import Button from 'components/base/Button' |
||||
|
import GrowScroll from 'components/base/GrowScroll' |
||||
|
import GradientBox from 'components/GradientBox' |
||||
|
|
||||
|
import { getCleanVersion } from 'components/ManagerPage/FirmwareUpdate' |
||||
|
|
||||
|
import type { ModalStatus } from 'components/ManagerPage/FirmwareUpdate' |
||||
|
|
||||
|
type FirmwareInfos = { |
||||
|
name: string, |
||||
|
notes: string, |
||||
|
} |
||||
|
|
||||
|
type Props = { |
||||
|
t: T, |
||||
|
status: ModalStatus, |
||||
|
firmware: FirmwareInfos, |
||||
|
goToNextStep: () => void, |
||||
|
onClose: () => void, |
||||
|
} |
||||
|
|
||||
|
type State = * |
||||
|
|
||||
|
class DisclaimerModal extends PureComponent<Props, State> { |
||||
|
render(): React$Node { |
||||
|
const { status, firmware, onClose, t, goToNextStep } = this.props |
||||
|
return ( |
||||
|
<Modal |
||||
|
isOpened={status === 'disclaimer'} |
||||
|
onClose={onClose} |
||||
|
render={({ onClose }) => ( |
||||
|
<ModalBody onClose={onClose} grow align="center" justify="center" mt={3}> |
||||
|
<Fragment> |
||||
|
<ModalTitle>{t('app:manager.firmware.update')}</ModalTitle> |
||||
|
<ModalContent> |
||||
|
<Text ff="Open Sans|Regular" fontSize={4} color="graphite" align="center"> |
||||
|
<Trans i18nKey="app:manager.firmware.disclaimerTitle"> |
||||
|
You are about to install the latest |
||||
|
<Text ff="Open Sans|SemiBold" color="dark"> |
||||
|
{`firmware ${firmware ? getCleanVersion(firmware.name) : ''}`} |
||||
|
</Text> |
||||
|
</Trans> |
||||
|
</Text> |
||||
|
<Text ff="Open Sans|Regular" fontSize={4} color="graphite" align="center"> |
||||
|
{t('app:manager.firmware.disclaimerAppDelete')} |
||||
|
{t('app:manager.firmware.disclaimerAppReinstall')} |
||||
|
</Text> |
||||
|
</ModalContent> |
||||
|
<ModalContent style={{ height: 250, width: '100%' }}> |
||||
|
<GrowScroll> |
||||
|
<Text ff="Open Sans|Regular" fontSize={4} color="graphite"> |
||||
|
{firmware.notes} |
||||
|
</Text> |
||||
|
</GrowScroll> |
||||
|
<GradientBox /> |
||||
|
</ModalContent> |
||||
|
<ModalFooter horizontal justifyContent="flex-end" style={{ width: '100%' }}> |
||||
|
<Button primary padded onClick={goToNextStep}> |
||||
|
{t('app:manager.firmware.continue')} |
||||
|
</Button> |
||||
|
</ModalFooter> |
||||
|
</Fragment> |
||||
|
</ModalBody> |
||||
|
)} |
||||
|
/> |
||||
|
) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
export default translate()(DisclaimerModal) |
@ -0,0 +1,122 @@ |
|||||
|
// @flow
|
||||
|
import React, { PureComponent, Fragment } from 'react' |
||||
|
import { translate } from 'react-i18next' |
||||
|
|
||||
|
import type { T } from 'types/common' |
||||
|
|
||||
|
import Modal from 'components/base/Modal' |
||||
|
import Stepper from 'components/base/Stepper' |
||||
|
import Button from 'components/base/Button' |
||||
|
import SyncSkipUnderPriority from 'components/SyncSkipUnderPriority' |
||||
|
|
||||
|
import type { StepProps as DefaultStepProps, Step } from 'components/base/Stepper' |
||||
|
import type { ModalStatus } from 'components/ManagerPage/FirmwareUpdate' |
||||
|
import type { LedgerScriptParams } from 'helpers/common' |
||||
|
|
||||
|
import StepOSUInstaller from './steps/01-step-osu-installer' |
||||
|
import StepFlashMcu from './steps/02-step-flash-mcu' |
||||
|
import StepConfirmation, { StepConfirmFooter } from './steps/03-step-confirmation' |
||||
|
|
||||
|
export type StepProps = DefaultStepProps & { |
||||
|
firmware: ?LedgerScriptParams, |
||||
|
onCloseModal: () => void, |
||||
|
} |
||||
|
|
||||
|
type StepId = 'idCheck' | 'updateMCU' | 'finish' |
||||
|
|
||||
|
// FIXME: Debugging for now to move between steps
|
||||
|
// Remove when plugged to firmware update
|
||||
|
function DebugFooter({ |
||||
|
transitionTo, |
||||
|
where, |
||||
|
}: { |
||||
|
where: string, |
||||
|
transitionTo: (where: string) => void, |
||||
|
}) { |
||||
|
return <Button onClick={() => transitionTo(where)}>{where}</Button> |
||||
|
} |
||||
|
|
||||
|
const createSteps = ({ t }: { t: T }) => [ |
||||
|
{ |
||||
|
id: 'idCheck', |
||||
|
label: t('app:manager.modal.steps.idCheck'), |
||||
|
component: StepOSUInstaller, |
||||
|
footer: ({ firmware, ...props }: StepProps) => ( |
||||
|
<DebugFooter firmware={firmware} {...props} where="updateMCU" /> |
||||
|
), |
||||
|
onBack: null, |
||||
|
hideFooter: false, |
||||
|
}, |
||||
|
{ |
||||
|
id: 'updateMCU', |
||||
|
label: t('app:manager.modal.steps.updateMCU'), |
||||
|
component: StepFlashMcu, |
||||
|
footer: ({ firmware, ...props }: StepProps) => ( |
||||
|
<Fragment> |
||||
|
<DebugFooter firmware={firmware} {...props} where="idCheck" /> |
||||
|
<DebugFooter firmware={firmware} {...props} where="finish" /> |
||||
|
</Fragment> |
||||
|
), |
||||
|
onBack: null, |
||||
|
hideFooter: false, |
||||
|
}, |
||||
|
{ |
||||
|
id: 'finish', |
||||
|
label: t('app:addAccounts.breadcrumb.finish'), |
||||
|
component: StepConfirmation, |
||||
|
footer: StepConfirmFooter, |
||||
|
onBack: null, |
||||
|
hideFooter: false, |
||||
|
}, |
||||
|
] |
||||
|
|
||||
|
type Props = { |
||||
|
t: T, |
||||
|
status: ModalStatus, |
||||
|
onClose: () => void, |
||||
|
firmware: ?LedgerScriptParams, |
||||
|
} |
||||
|
|
||||
|
type State = { |
||||
|
stepId: StepId | string, |
||||
|
} |
||||
|
|
||||
|
class UpdateModal extends PureComponent<Props, State> { |
||||
|
state = { |
||||
|
stepId: 'idCheck', |
||||
|
} |
||||
|
|
||||
|
STEPS = createSteps({ t: this.props.t }) |
||||
|
|
||||
|
handleStepChange = (step: Step) => this.setState({ stepId: step.id }) |
||||
|
|
||||
|
render(): React$Node { |
||||
|
const { status, t, firmware, onClose } = this.props |
||||
|
const { stepId } = this.state |
||||
|
|
||||
|
const additionalProps = { |
||||
|
firmware, |
||||
|
onCloseModal: onClose, |
||||
|
} |
||||
|
|
||||
|
return ( |
||||
|
<Modal |
||||
|
onClose={onClose} |
||||
|
isOpened={status === 'install'} |
||||
|
refocusWhenChange={stepId} |
||||
|
render={() => ( |
||||
|
<Stepper |
||||
|
title={t('app:manager.firmware.update')} |
||||
|
initialStepId="idCheck" |
||||
|
steps={this.STEPS} |
||||
|
{...additionalProps} |
||||
|
> |
||||
|
<SyncSkipUnderPriority priority={100} /> |
||||
|
</Stepper> |
||||
|
)} |
||||
|
/> |
||||
|
) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
export default translate()(UpdateModal) |
@ -0,0 +1,72 @@ |
|||||
|
// @flow
|
||||
|
|
||||
|
import React from 'react' |
||||
|
import styled from 'styled-components' |
||||
|
|
||||
|
import Box from 'components/base/Box' |
||||
|
import Text from 'components/base/Text' |
||||
|
import Button from 'components/base/Button' |
||||
|
import DeviceConfirm from 'components/DeviceConfirm' |
||||
|
|
||||
|
import type { StepProps } from '../' |
||||
|
|
||||
|
const Container = styled(Box).attrs({ |
||||
|
alignItems: 'center', |
||||
|
fontSize: 4, |
||||
|
color: 'dark', |
||||
|
px: 7, |
||||
|
})`` |
||||
|
|
||||
|
const Title = styled(Box).attrs({ |
||||
|
ff: 'Museo Sans|Regular', |
||||
|
fontSize: 5, |
||||
|
mb: 3, |
||||
|
})`` |
||||
|
|
||||
|
const Address = styled(Box).attrs({ |
||||
|
bg: p => (p.notValid ? 'transparent' : p.withQRCode ? 'white' : 'lightGrey'), |
||||
|
borderRadius: 1, |
||||
|
color: 'dark', |
||||
|
ff: 'Open Sans|SemiBold', |
||||
|
fontSize: 4, |
||||
|
mt: 2, |
||||
|
px: p => (p.notValid ? 0 : 4), |
||||
|
py: p => (p.notValid ? 0 : 3), |
||||
|
})` |
||||
|
border: ${p => (p.notValid ? 'none' : `1px dashed ${p.theme.colors.fog}`)}; |
||||
|
cursor: text; |
||||
|
user-select: text; |
||||
|
width: 325px; |
||||
|
` |
||||
|
|
||||
|
const Ellipsis = styled.span` |
||||
|
white-space: nowrap; |
||||
|
overflow: hidden; |
||||
|
text-overflow: ellipsis; |
||||
|
width: 100%; |
||||
|
` |
||||
|
|
||||
|
// TODO: Change to class component and add osu firmware install
|
||||
|
function StepFullFirmwareInstall({ t, firmware }: StepProps) { |
||||
|
return ( |
||||
|
<Container> |
||||
|
<Title>{t('app:manager.modal.confirmIdentifier')}</Title> |
||||
|
<Text ff="Open Sans|Regular" align="center" color="smoke"> |
||||
|
{t('app:manager.modal.confirmIdentifierText')} |
||||
|
</Text> |
||||
|
<Box mx={7} mt={5}> |
||||
|
<Text ff="Open Sans|SemiBold" align="center" color="smoke"> |
||||
|
{t('app:manager.modal.identifier')} |
||||
|
</Text> |
||||
|
<Address> |
||||
|
<Ellipsis>{firmware && firmware.hash}</Ellipsis> |
||||
|
</Address> |
||||
|
</Box> |
||||
|
<Box mt={5}> |
||||
|
<DeviceConfirm /> |
||||
|
</Box> |
||||
|
</Container> |
||||
|
) |
||||
|
} |
||||
|
|
||||
|
export default StepFullFirmwareInstall |
@ -0,0 +1,72 @@ |
|||||
|
// @flow
|
||||
|
|
||||
|
import React from 'react' |
||||
|
import styled from 'styled-components' |
||||
|
|
||||
|
import Box from 'components/base/Box' |
||||
|
import Text from 'components/base/Text' |
||||
|
import Button from 'components/base/Button' |
||||
|
import DeviceConfirm from 'components/DeviceConfirm' |
||||
|
|
||||
|
import type { StepProps } from '../' |
||||
|
|
||||
|
const Container = styled(Box).attrs({ |
||||
|
alignItems: 'center', |
||||
|
fontSize: 4, |
||||
|
color: 'dark', |
||||
|
px: 7, |
||||
|
})`` |
||||
|
|
||||
|
const Title = styled(Box).attrs({ |
||||
|
ff: 'Museo Sans|Regular', |
||||
|
fontSize: 5, |
||||
|
mb: 3, |
||||
|
})`` |
||||
|
|
||||
|
const Address = styled(Box).attrs({ |
||||
|
bg: p => (p.notValid ? 'transparent' : p.withQRCode ? 'white' : 'lightGrey'), |
||||
|
borderRadius: 1, |
||||
|
color: 'dark', |
||||
|
ff: 'Open Sans|SemiBold', |
||||
|
fontSize: 4, |
||||
|
mt: 2, |
||||
|
px: p => (p.notValid ? 0 : 4), |
||||
|
py: p => (p.notValid ? 0 : 3), |
||||
|
})` |
||||
|
border: ${p => (p.notValid ? 'none' : `1px dashed ${p.theme.colors.fog}`)}; |
||||
|
cursor: text; |
||||
|
user-select: text; |
||||
|
width: 325px; |
||||
|
` |
||||
|
|
||||
|
const Ellipsis = styled.span` |
||||
|
white-space: nowrap; |
||||
|
overflow: hidden; |
||||
|
text-overflow: ellipsis; |
||||
|
width: 100%; |
||||
|
` |
||||
|
|
||||
|
// TODO: Change to class component and add osu firmware install
|
||||
|
function StepOSUInstaller({ t, firmware }: StepProps) { |
||||
|
return ( |
||||
|
<Container> |
||||
|
<Title>{t('app:manager.modal.confirmIdentifier')}</Title> |
||||
|
<Text ff="Open Sans|Regular" align="center" color="smoke"> |
||||
|
{t('app:manager.modal.confirmIdentifierText')} |
||||
|
</Text> |
||||
|
<Box mx={7} mt={5}> |
||||
|
<Text ff="Open Sans|SemiBold" align="center" color="smoke"> |
||||
|
{t('app:manager.modal.identifier')} |
||||
|
</Text> |
||||
|
<Address> |
||||
|
<Ellipsis>{firmware && firmware.hash}</Ellipsis> |
||||
|
</Address> |
||||
|
</Box> |
||||
|
<Box mt={5}> |
||||
|
<DeviceConfirm /> |
||||
|
</Box> |
||||
|
</Container> |
||||
|
) |
||||
|
} |
||||
|
|
||||
|
export default StepOSUInstaller |
@ -0,0 +1,70 @@ |
|||||
|
// @flow
|
||||
|
|
||||
|
import React from 'react' |
||||
|
import styled from 'styled-components' |
||||
|
|
||||
|
import { i } from 'helpers/staticPath' |
||||
|
|
||||
|
import Box from 'components/base/Box' |
||||
|
import Text from 'components/base/Text' |
||||
|
|
||||
|
import type { StepProps } from '../' |
||||
|
|
||||
|
const Container = styled(Box).attrs({ |
||||
|
alignItems: 'center', |
||||
|
fontSize: 4, |
||||
|
color: 'dark', |
||||
|
})`` |
||||
|
|
||||
|
const Title = styled(Box).attrs({ |
||||
|
ff: 'Museo Sans|Regular', |
||||
|
fontSize: 5, |
||||
|
mb: 3, |
||||
|
})`` |
||||
|
|
||||
|
const Bullet = styled.span` |
||||
|
font-weight: 600; |
||||
|
color: #142533; |
||||
|
` |
||||
|
|
||||
|
const Separator = styled(Box).attrs({ |
||||
|
color: 'fog', |
||||
|
})` |
||||
|
height: 1px; |
||||
|
width: 100%; |
||||
|
background-color: currentColor; |
||||
|
` |
||||
|
|
||||
|
// TODO: Change to class component and add flash mcu and final
|
||||
|
function StepFlashMcu({ t }: StepProps) { |
||||
|
return ( |
||||
|
<Container> |
||||
|
<Title>{t('app:manager.modal.mcuTitle')}</Title> |
||||
|
<Box mx={7}> |
||||
|
<Text ff="Open Sans|Regular" align="center" color="smoke"> |
||||
|
<Bullet>{'1.'}</Bullet> |
||||
|
{t('app:manager.modal.mcuFirst')} |
||||
|
</Text> |
||||
|
<img |
||||
|
src={i('logos/unplugDevice.png')} |
||||
|
style={{ width: '100%', maxWidth: 330, marginTop: 30 }} |
||||
|
alt={t('app:manager.modal.mcuFirst')} |
||||
|
/> |
||||
|
</Box> |
||||
|
<Separator my={6} /> |
||||
|
<Box mx={7}> |
||||
|
<Text ff="Open Sans|Regular" align="center" color="smoke"> |
||||
|
<Bullet>{'2.'}</Bullet> |
||||
|
{t('app:manager.modal.mcuSecond')} |
||||
|
</Text> |
||||
|
<img |
||||
|
src={i('logos/unplugDevice.png')} |
||||
|
style={{ width: '100%', maxWidth: 330, marginTop: 30 }} |
||||
|
alt={t('app:manager.modal.mcuFirst')} |
||||
|
/> |
||||
|
</Box> |
||||
|
</Container> |
||||
|
) |
||||
|
} |
||||
|
|
||||
|
export default StepFlashMcu |
@ -0,0 +1,52 @@ |
|||||
|
// @flow
|
||||
|
|
||||
|
import React from 'react' |
||||
|
import styled from 'styled-components' |
||||
|
|
||||
|
import Box from 'components/base/Box' |
||||
|
import Text from 'components/base/Text' |
||||
|
import Button from 'components/base/Button' |
||||
|
import CheckCircle from 'icons/CheckCircle' |
||||
|
|
||||
|
import type { StepProps } from '../' |
||||
|
|
||||
|
const Container = styled(Box).attrs({ |
||||
|
alignItems: 'center', |
||||
|
fontSize: 4, |
||||
|
color: 'dark', |
||||
|
})`` |
||||
|
|
||||
|
const Title = styled(Box).attrs({ |
||||
|
fontFamily: 'Museo Sans', |
||||
|
fontSize: 6, |
||||
|
color: 'dark', |
||||
|
})` |
||||
|
font-weight: 500; |
||||
|
` |
||||
|
|
||||
|
function StepConfirmation({ t }: StepProps) { |
||||
|
return ( |
||||
|
<Container> |
||||
|
<Box mx={7} color="positiveGreen" my={4}> |
||||
|
<CheckCircle size={44} /> |
||||
|
</Box> |
||||
|
<Title>{t('app:manager.modal.successTitle')}</Title> |
||||
|
<Box mt={2} mb={8}> |
||||
|
<Text ff="Open Sans|Regular" fontSize={4} color="graphite"> |
||||
|
{t('app:manager.modal.successText')} |
||||
|
</Text> |
||||
|
</Box> |
||||
|
<Box mx={7} /> |
||||
|
</Container> |
||||
|
) |
||||
|
} |
||||
|
|
||||
|
export function StepConfirmFooter({ t, onCloseModal }: StepProps) { |
||||
|
return ( |
||||
|
<Button primary onClick={onCloseModal}> |
||||
|
{t('app:common.close')} |
||||
|
</Button> |
||||
|
) |
||||
|
} |
||||
|
|
||||
|
export default StepConfirmation |
After Width: | Height: | Size: 10 KiB |
Loading…
Reference in new issue