|
|
@ -13,8 +13,14 @@ import type { Device, T } from 'types/common' |
|
|
|
import { MODAL_ADD_ACCOUNT } from 'config/constants' |
|
|
|
|
|
|
|
import { closeModal } from 'reducers/modals' |
|
|
|
import { canCreateAccount, getAccounts, getArchivedAccounts } from 'reducers/accounts' |
|
|
|
import { sendEvent } from 'renderer/events' |
|
|
|
import { |
|
|
|
canCreateAccount, |
|
|
|
getAccounts, |
|
|
|
getArchivedAccounts, |
|
|
|
decodeAccount, |
|
|
|
} from 'reducers/accounts' |
|
|
|
|
|
|
|
import { runJob } from 'renderer/events' |
|
|
|
|
|
|
|
import { addAccount, updateAccount } from 'actions/accounts' |
|
|
|
|
|
|
@ -35,7 +41,7 @@ const GET_STEPS = t => [ |
|
|
|
] |
|
|
|
|
|
|
|
const mapStateToProps = state => ({ |
|
|
|
accounts: getAccounts(state), |
|
|
|
existingAccounts: getAccounts(state), |
|
|
|
archivedAccounts: getArchivedAccounts(state), |
|
|
|
canCreateAccount: canCreateAccount(state), |
|
|
|
}) |
|
|
@ -47,7 +53,7 @@ const mapDispatchToProps = { |
|
|
|
} |
|
|
|
|
|
|
|
type Props = { |
|
|
|
accounts: Account[], |
|
|
|
existingAccounts: Account[], |
|
|
|
addAccount: Function, |
|
|
|
archivedAccounts: Account[], |
|
|
|
canCreateAccount: boolean, |
|
|
@ -57,23 +63,29 @@ type Props = { |
|
|
|
} |
|
|
|
|
|
|
|
type State = { |
|
|
|
accountsImport: Object, |
|
|
|
stepIndex: number, |
|
|
|
|
|
|
|
currency: ?CryptoCurrency, |
|
|
|
deviceSelected: ?Device, |
|
|
|
|
|
|
|
selectedAccounts: Account[], |
|
|
|
scannedAccounts: Account[], |
|
|
|
|
|
|
|
// TODO: what's that.
|
|
|
|
fetchingCounterValues: boolean, |
|
|
|
selectedAccounts: Array<number>, |
|
|
|
appStatus: ?string, |
|
|
|
stepIndex: number, |
|
|
|
} |
|
|
|
|
|
|
|
const INITIAL_STATE = { |
|
|
|
accountsImport: {}, |
|
|
|
stepIndex: 0, |
|
|
|
currency: null, |
|
|
|
deviceSelected: null, |
|
|
|
fetchingCounterValues: false, |
|
|
|
|
|
|
|
selectedAccounts: [], |
|
|
|
scannedAccounts: [], |
|
|
|
|
|
|
|
fetchingCounterValues: false, |
|
|
|
appStatus: null, |
|
|
|
stepIndex: 0, |
|
|
|
} |
|
|
|
|
|
|
|
class AddAccountModal extends PureComponent<Props, State> { |
|
|
@ -88,29 +100,41 @@ class AddAccountModal extends PureComponent<Props, State> { |
|
|
|
const { stepIndex: nextStepIndex } = nextState |
|
|
|
|
|
|
|
if (!fetchingCounterValues && stepIndex === 0 && nextStepIndex === 1) { |
|
|
|
// TODO: seems shady to do this here..............
|
|
|
|
await this.fetchCounterValues() |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
componentWillUnmount() { |
|
|
|
this.killProcess() |
|
|
|
this.handleReset() |
|
|
|
ipcRenderer.removeListener('msg', this.handleMsgEvent) |
|
|
|
clearTimeout(this._timeout) |
|
|
|
} |
|
|
|
|
|
|
|
importsAccounts() { |
|
|
|
const { accounts } = this.props |
|
|
|
async startScanAccountsDevice() { |
|
|
|
const { deviceSelected, currency } = this.state |
|
|
|
|
|
|
|
if (!deviceSelected || !currency) { |
|
|
|
return |
|
|
|
} |
|
|
|
|
|
|
|
sendEvent('usb', 'wallet.getAccounts', { |
|
|
|
pathDevice: deviceSelected.path, |
|
|
|
currencyId: currency.id, |
|
|
|
currentAccounts: accounts.map(acc => acc.id), |
|
|
|
}) |
|
|
|
try { |
|
|
|
// scan every account for given currency and device
|
|
|
|
await runJob({ |
|
|
|
channel: 'usb', |
|
|
|
job: 'wallet.scanAccountsOnDevice', |
|
|
|
successResponse: 'wallet.scanAccountsOnDevice.success', |
|
|
|
errorResponse: 'wallet.scanAccountsOnDevice.fail', |
|
|
|
data: { |
|
|
|
devicePath: deviceSelected.path, |
|
|
|
currencyId: currency.id, |
|
|
|
}, |
|
|
|
}) |
|
|
|
|
|
|
|
// go to final step
|
|
|
|
this.setState({ stepIndex: 3 }) |
|
|
|
} catch (err) { |
|
|
|
console.log(err) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
async fetchCounterValues() { |
|
|
@ -160,75 +184,46 @@ class AddAccountModal extends PureComponent<Props, State> { |
|
|
|
_steps = GET_STEPS(this.props.t) |
|
|
|
|
|
|
|
handleMsgEvent = (e, { data, type }) => { |
|
|
|
const { accountsImport, currency } = this.state |
|
|
|
const { addAccount } = this.props |
|
|
|
const { addAccount, existingAccounts } = this.props |
|
|
|
|
|
|
|
if (type === 'wallet.getAccounts.start') { |
|
|
|
this._pid = data.pid |
|
|
|
} |
|
|
|
|
|
|
|
if (type === 'wallet.getAccounts.progress') { |
|
|
|
this.setState(prev => ({ |
|
|
|
stepIndex: 2, |
|
|
|
accountsImport: { |
|
|
|
...(data !== null |
|
|
|
? { |
|
|
|
[data.id]: { |
|
|
|
...data, |
|
|
|
name: `Account ${data.accountIndex + 1}`, |
|
|
|
}, |
|
|
|
} |
|
|
|
: {}), |
|
|
|
...prev.accountsImport, |
|
|
|
}, |
|
|
|
})) |
|
|
|
if (type === 'wallet.scanAccountsOnDevice.accountScanned') { |
|
|
|
// create Account from AccountRaw account scanned on device
|
|
|
|
const account = { |
|
|
|
...decodeAccount(data), |
|
|
|
archived: true, |
|
|
|
} |
|
|
|
|
|
|
|
if (currency && data && data.finish) { |
|
|
|
const { accountIndex, finish, ...account } = data |
|
|
|
addAccount({ |
|
|
|
...account, |
|
|
|
// As data is passed inside electron event system,
|
|
|
|
// dates are converted to their string equivalent
|
|
|
|
//
|
|
|
|
// so, quick & dirty way to put back Date objects
|
|
|
|
operations: account.operations.map(op => ({ |
|
|
|
...op, |
|
|
|
date: new Date(op.date), |
|
|
|
})), |
|
|
|
name: `Account ${accountIndex + 1}`, |
|
|
|
archived: true, |
|
|
|
currency, |
|
|
|
unit: currency.units[0], |
|
|
|
}) |
|
|
|
// add it to the reducer if needed, archived
|
|
|
|
if (!existingAccounts.find(a => a.id === account.id)) { |
|
|
|
addAccount(account) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (type === 'wallet.getAccounts.success') { |
|
|
|
this.setState({ |
|
|
|
selectedAccounts: Object.keys(accountsImport).map(k => accountsImport[k].id), |
|
|
|
stepIndex: 3, |
|
|
|
}) |
|
|
|
this.setState(state => ({ |
|
|
|
scannedAccounts: [...state.scannedAccounts, account], |
|
|
|
})) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
handleChangeDevice = d => this.setState({ deviceSelected: d }) |
|
|
|
|
|
|
|
handleSelectAccount = a => () => |
|
|
|
this.setState(prev => ({ |
|
|
|
selectedAccounts: prev.selectedAccounts.includes(a) |
|
|
|
? prev.selectedAccounts.filter(x => x !== a) |
|
|
|
: [a, ...prev.selectedAccounts], |
|
|
|
})) |
|
|
|
handleToggleAccount = account => { |
|
|
|
const { selectedAccounts } = this.state |
|
|
|
const isSelected = selectedAccounts.find(a => a === account) |
|
|
|
this.setState({ |
|
|
|
selectedAccounts: isSelected |
|
|
|
? selectedAccounts.filter(a => a !== account) |
|
|
|
: [...selectedAccounts, account], |
|
|
|
}) |
|
|
|
} |
|
|
|
|
|
|
|
handleChangeCurrency = (currency: CryptoCurrency) => this.setState({ currency }) |
|
|
|
|
|
|
|
handleChangeStatus = (deviceStatus, appStatus) => this.setState({ appStatus }) |
|
|
|
|
|
|
|
handleImportAccount = () => { |
|
|
|
const { archivedAccounts, updateAccount, closeModal } = this.props |
|
|
|
const { updateAccount } = this.props |
|
|
|
const { selectedAccounts } = this.state |
|
|
|
const accounts = archivedAccounts.filter(a => selectedAccounts.includes(a.id)) |
|
|
|
accounts.forEach(a => updateAccount({ ...a, archived: false })) |
|
|
|
selectedAccounts.forEach(a => updateAccount({ ...a, archived: false })) |
|
|
|
this.setState({ selectedAccounts: [] }) |
|
|
|
closeModal(MODAL_ADD_ACCOUNT) |
|
|
|
} |
|
|
@ -242,22 +237,12 @@ class AddAccountModal extends PureComponent<Props, State> { |
|
|
|
} |
|
|
|
|
|
|
|
handleReset = () => { |
|
|
|
this.killProcess() |
|
|
|
clearTimeout(this._timeout) |
|
|
|
this.setState(INITIAL_STATE) |
|
|
|
} |
|
|
|
|
|
|
|
killProcess = () => |
|
|
|
sendEvent('msg', 'kill.process', { |
|
|
|
pid: this._pid, |
|
|
|
}) |
|
|
|
|
|
|
|
_timeout = undefined |
|
|
|
_pid = null |
|
|
|
|
|
|
|
renderStep() { |
|
|
|
const { accounts, archivedAccounts, t } = this.props |
|
|
|
const { stepIndex, currency, accountsImport, deviceSelected, selectedAccounts } = this.state |
|
|
|
const { t, existingAccounts } = this.props |
|
|
|
const { stepIndex, scannedAccounts, currency, deviceSelected, selectedAccounts } = this.state |
|
|
|
const step = this._steps[stepIndex] |
|
|
|
if (!step) { |
|
|
|
return null |
|
|
@ -269,31 +254,28 @@ class AddAccountModal extends PureComponent<Props, State> { |
|
|
|
const stepProps = { |
|
|
|
t, |
|
|
|
currency, |
|
|
|
// STEP CURRENCY
|
|
|
|
...props(stepIndex === 0, { |
|
|
|
onChangeCurrency: this.handleChangeCurrency, |
|
|
|
}), |
|
|
|
// STEP CONNECT DEVICE
|
|
|
|
...props(stepIndex === 1, { |
|
|
|
deviceSelected, |
|
|
|
onStatusChange: this.handleChangeStatus, |
|
|
|
onChangeDevice: this.handleChangeDevice, |
|
|
|
}), |
|
|
|
// STEP ACCOUNT IMPORT PROGRESS
|
|
|
|
...props(stepIndex === 2, { |
|
|
|
accountsImport, |
|
|
|
importProgress: true, |
|
|
|
selectedAccounts, |
|
|
|
scannedAccounts, |
|
|
|
existingAccounts, |
|
|
|
}), |
|
|
|
// STEP FINISH AND SELECT ACCOUNTS
|
|
|
|
...props(stepIndex === 3, { |
|
|
|
accountsImport: Object.keys(accountsImport).reduce((result, k) => { |
|
|
|
const account = accountsImport[k] |
|
|
|
const existingAccount = accounts.find(a => a.id === account.id) |
|
|
|
if (!existingAccount || (existingAccount && existingAccount.archived)) { |
|
|
|
result[account.id] = account |
|
|
|
} |
|
|
|
return result |
|
|
|
}, {}), |
|
|
|
archivedAccounts: archivedAccounts.filter(a => !accountsImport[a.id]), |
|
|
|
importProgress: false, |
|
|
|
onSelectAccount: this.handleSelectAccount, |
|
|
|
onToggleAccount: this.handleToggleAccount, |
|
|
|
selectedAccounts, |
|
|
|
scannedAccounts, |
|
|
|
existingAccounts, |
|
|
|
}), |
|
|
|
} |
|
|
|
|
|
|
@ -310,7 +292,7 @@ class AddAccountModal extends PureComponent<Props, State> { |
|
|
|
case 1: |
|
|
|
onClick = () => { |
|
|
|
this.handleNextStep() |
|
|
|
this.importsAccounts() |
|
|
|
this.startScanAccountsDevice() |
|
|
|
} |
|
|
|
break |
|
|
|
|
|
|
|