Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions packages/neuron-ui/src/components/ImportHardware/common.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* eslint-disable import/prefer-default-export */
import { FailureFromController } from 'services/remote/remoteApiWrapper'

export enum RoutePath {
export enum ImportStep {
DetectDevice = '/detect-device',
Comfirming = '/confirming',
Error = '/error',
Expand All @@ -15,12 +15,14 @@ export interface Model {
product: string
}

export interface LocationState {
entryPath: string
model: Model
export interface ImportHardwareState {
model?: Model
extendedPublicKey?: {
publicKey: string
chainCode: string
}
error?: FailureFromController['message']
step: ImportStep
}

export type ActionType = Partial<ImportHardwareState>
43 changes: 21 additions & 22 deletions packages/neuron-ui/src/components/ImportHardware/confirming.tsx
Original file line number Diff line number Diff line change
@@ -1,42 +1,41 @@
import React, { useCallback } from 'react'
import React, { useCallback, useEffect } from 'react'
import { useTranslation } from 'react-i18next'
import { RouteComponentProps } from 'react-router-dom'
import Button from 'widgets/Button'
import { ReactComponent as PendingIcon } from 'widgets/Icons/Pending.svg'
import { getDeviceExtendedPublickey } from 'services/remote'
import { isSuccessResponse, useDidMount } from 'utils'
import { RoutePath, LocationState } from './common'
import { isSuccessResponse } from 'utils'
import { ImportStep, ActionType } from './common'

import styles from './findDevice.module.scss'

const Confirming = ({ history, location }: RouteComponentProps<{}, {}, LocationState>) => {
const Confirming = ({ dispatch }: { dispatch: React.Dispatch<ActionType> }) => {
const [t] = useTranslation()
const { entryPath } = location.state
const onBack = useCallback(() => {
history.push(entryPath)
}, [history, entryPath])
dispatch({ step: ImportStep.ImportHardware })
}, [dispatch])

useDidMount(() => {
useEffect(() => {
let cancel = false
getDeviceExtendedPublickey().then(res => {
if (cancel) {
return
}
if (isSuccessResponse(res)) {
history.push({
pathname: entryPath + RoutePath.NameWallet,
state: {
...location.state,
extendedPublicKey: res.result!,
},
dispatch({
step: ImportStep.NameWallet,
extendedPublicKey: res.result!,
})
} else {
history.push({
pathname: entryPath + RoutePath.Error,
state: {
...location.state,
error: res.message,
},
dispatch({
step: ImportStep.Error,
error: res.message,
})
}
})
})
return () => {
cancel = true
}
}, [])

return (
<div className={styles.container}>
Expand Down
18 changes: 6 additions & 12 deletions packages/neuron-ui/src/components/ImportHardware/detect-device.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import React, { useCallback, useState } from 'react'
import { useHistory, RouteComponentProps } from 'react-router-dom'
import { useTranslation } from 'react-i18next'
import Button from 'widgets/Button'
import { getDevices, getDeviceFirmwareVersion, getDeviceCkbAppVersion, connectDevice } from 'services/remote'
Expand All @@ -12,7 +11,7 @@ import {
DeviceNotFoundException,
MultiDeviceException,
} from 'exceptions'
import { RoutePath, LocationState } from './common'
import { ImportStep, ActionType, Model } from './common'

import styles from './findDevice.module.scss'

Expand Down Expand Up @@ -45,13 +44,11 @@ const Info = (
)
}

const DetectDevice = ({ history, location }: RouteComponentProps<{}, {}, LocationState>) => {
const DetectDevice = ({ dispatch, model }: { dispatch: React.Dispatch<ActionType>; model: Model }) => {
const [t] = useTranslation()
const histroy = useHistory()
const { model, entryPath } = location.state
const onBack = useCallback(() => {
histroy.goBack()
}, [histroy])
dispatch({ step: ImportStep.ImportHardware })
}, [dispatch])

const [scaning, setScaning] = useState(true)
const [error, setError] = useState('')
Expand Down Expand Up @@ -99,11 +96,8 @@ const DetectDevice = ({ history, location }: RouteComponentProps<{}, {}, Locatio
})

const onNext = useCallback(() => {
history.push({
pathname: entryPath + RoutePath.Comfirming,
state: location.state,
})
}, [history, entryPath, location.state])
dispatch({ step: ImportStep.Comfirming })
}, [dispatch])

const errorMsg = error.startsWith('messages.codes.') ? t(error) : error
const ready = error === '' && appVersion !== ''
Expand Down
18 changes: 11 additions & 7 deletions packages/neuron-ui/src/components/ImportHardware/import-error.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,26 @@
import React, { useCallback } from 'react'
import { useTranslation } from 'react-i18next'
import { RouteComponentProps } from 'react-router-dom'
import Button from 'widgets/Button'
import CopyZone from 'widgets/CopyZone'
import { ReactComponent as FailedInfo } from 'widgets/Icons/FailedInfo.svg'
import { errorFormatter } from 'utils'
import { LocationState } from './common'
import { ActionType, ImportHardwareState, ImportStep } from './common'

import styles from './findDevice.module.scss'

const ImportError = ({ history, location }: RouteComponentProps<{}, {}, LocationState>) => {
const ImportError = ({
dispatch,
error,
}: {
dispatch: React.Dispatch<ActionType>
error: ImportHardwareState['error']
}) => {
const [t] = useTranslation()
const { error, entryPath } = location.state
const onBack = useCallback(() => {
history.push(entryPath)
}, [history, entryPath])
dispatch({ step: ImportStep.ImportHardware })
}, [dispatch])

const errorMsg = errorFormatter(error!, t)
const errorMsg = error ? errorFormatter(error, t) : ''

return (
<div className={styles.container}>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
import React, { useCallback } from 'react'
import { useTranslation } from 'react-i18next'
import { RouteComponentProps } from 'react-router-dom'
import Button from 'widgets/Button'
import { ReactComponent as CompleteIcon } from 'widgets/Icons/Complete.svg'
import { RoutePath, LocationState } from './common'
import { ImportStep, ActionType } from './common'

import styles from './findDevice.module.scss'

const ImportSuccess = ({ history, location }: RouteComponentProps<{}, {}, LocationState>) => {
const ImportSuccess = ({ dispatch }: { dispatch: React.Dispatch<ActionType> }) => {
const [t] = useTranslation()
const { entryPath } = location.state
const onClose = useCallback(() => {
history.push(entryPath.replace(RoutePath.ImportHardware, ''))
}, [history, entryPath])
dispatch({ step: ImportStep.ImportHardware })
}, [])

return (
<div className={styles.container}>
Expand Down
46 changes: 34 additions & 12 deletions packages/neuron-ui/src/components/ImportHardware/index.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,46 @@
import React, { useRef, useEffect } from 'react'
import { Switch, Route, RouteComponentProps } from 'react-router-dom'
import React, { useRef, useEffect, useReducer } from 'react'
import Experimental from 'widgets/ExperimentalRibbon'
import Comfirming from './confirming'
import ImportError from './import-error'
import SelectModel from './select-model'
import DetectDevice from './detect-device'
import ImportSuccess from './import-success'
import NameWallet from './name-wallet'
import { RoutePath } from './common'
import { ImportStep, ImportHardwareState, ActionType } from './common'

import styles from './findDevice.module.scss'

const ImportHardware = ({ match }: RouteComponentProps) => {
const reducer: React.Reducer<ImportHardwareState, ActionType> = (state, action) => {
return { ...state, ...action }
}

const Content = () => {
const [importHardwareStates, dispatch] = useReducer(reducer, { step: ImportStep.ImportHardware })
switch (importHardwareStates.step) {
case ImportStep.ImportHardware:
return <SelectModel dispatch={dispatch} />
case ImportStep.DetectDevice:
return <DetectDevice dispatch={dispatch} model={importHardwareStates.model!} />
case ImportStep.Comfirming:
return <Comfirming dispatch={dispatch} />
case ImportStep.Error:
return <ImportError dispatch={dispatch} error={importHardwareStates.error} />
case ImportStep.Success:
return <ImportSuccess dispatch={dispatch} />
case ImportStep.NameWallet:
return (
<NameWallet
dispatch={dispatch}
model={importHardwareStates.model}
extendedPublicKey={importHardwareStates.extendedPublicKey}
/>
)
default:
return <SelectModel dispatch={dispatch} />
}
}

const ImportHardware = () => {
const dialogRef = useRef<HTMLDialogElement | null>(null)
const EXPERIMENTAL_TAG = 'import-hardware'

Expand All @@ -22,14 +51,7 @@ const ImportHardware = ({ match }: RouteComponentProps) => {
return (
<dialog ref={dialogRef} className={styles.dialog}>
<Experimental tag={EXPERIMENTAL_TAG} showRibbon={false} message="messages.experimental-message-hardware" />
<Switch>
<Route component={SelectModel} exact path={match.url} />
<Route component={DetectDevice} exact path={match.url + RoutePath.DetectDevice} />
<Route component={Comfirming} exact path={match.url + RoutePath.Comfirming} />
<Route component={ImportError} exact path={match.url + RoutePath.Error} />
<Route component={ImportSuccess} exact path={match.url + RoutePath.Success} />
<Route component={NameWallet} exact path={match.url + RoutePath.NameWallet} />
</Switch>
<Content />
</dialog>
)
}
Expand Down
27 changes: 15 additions & 12 deletions packages/neuron-ui/src/components/ImportHardware/name-wallet.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,29 @@
import React, { useCallback, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { RouteComponentProps } from 'react-router-dom'
import Button from 'widgets/Button'
import TextField from 'widgets/TextField'
import { createHardwareWallet } from 'services/remote'
import { isSuccessResponse } from 'utils'
import { RoutePath, LocationState } from './common'
import { ImportStep, ActionType, ImportHardwareState } from './common'

import styles from './findDevice.module.scss'

const NameWallet = ({ history, location }: RouteComponentProps<{}, {}, LocationState>) => {
const NameWallet = ({
dispatch,
model,
extendedPublicKey,
}: {
dispatch: React.Dispatch<ActionType>
model: ImportHardwareState['model']
extendedPublicKey: ImportHardwareState['extendedPublicKey']
}) => {
const [t] = useTranslation()
const { entryPath, model, extendedPublicKey } = location.state
const [walletName, setWalletName] = useState(`${model.manufacturer} ${model.product}`)
const [walletName, setWalletName] = useState(`${model?.manufacturer} ${model?.product}`)
const [errorMsg, setErrorMsg] = useState('')

const onBack = useCallback(() => {
history.push(entryPath)
}, [history, entryPath])
dispatch({ step: ImportStep.ImportHardware })
}, [dispatch])

const onNext = useCallback(
(e: React.FormEvent) => {
Expand All @@ -27,16 +33,13 @@ const NameWallet = ({ history, location }: RouteComponentProps<{}, {}, LocationS
walletName,
}).then(res => {
if (isSuccessResponse(res)) {
history.push({
pathname: entryPath + RoutePath.Success,
state: location.state,
})
dispatch({ step: ImportStep.Success })
} else {
setErrorMsg(typeof res.message === 'string' ? res.message : res.message!.content!)
}
})
},
[history, entryPath, walletName, location.state, extendedPublicKey]
[walletName, extendedPublicKey]
)

const onInput = useCallback(e => {
Expand Down
25 changes: 10 additions & 15 deletions packages/neuron-ui/src/components/ImportHardware/select-model.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import React, { useCallback, useState } from 'react'
import { RouteComponentProps } from 'react-router-dom'
import { useTranslation } from 'react-i18next'
import Button from 'widgets/Button'
import Select from 'widgets/Select'
import { Text } from 'office-ui-fabric-react'
import { useHistory } from 'react-router-dom'
import { useGoBack } from 'utils'
import styles from './findDevice.module.scss'
import { LocationState, Model, RoutePath } from './common'
import { ActionType, Model, ImportStep } from './common'

const supportedHardwareModels = [
{
Expand All @@ -26,23 +27,17 @@ const supportedHardwareModels = [
},
]

const SelectModel = ({ match, history }: RouteComponentProps<{}, {}, LocationState>) => {
const SelectModel = ({ dispatch }: { dispatch: React.Dispatch<ActionType> }) => {
const [t] = useTranslation()
const [model, setModel] = useState<Model>()

const onBack = useCallback(() => {
history.push(match.url.replace(RoutePath.ImportHardware, ''))
}, [history, match.url])

const history = useHistory()
const onBack = useGoBack(history)
const onNext = useCallback(() => {
history.push({
pathname: match.url + RoutePath.DetectDevice,
state: {
model: model!,
entryPath: match.url,
},
dispatch({
model,
step: ImportStep.DetectDevice,
})
}, [history, match.url, model])
}, [dispatch, model])

const onDropDownChange = useCallback(({ data }) => {
setModel(data)
Expand Down