import React, { PureComponent } from 'react'; import PropTypes from 'prop-types'; import classnames from 'classnames'; import Button from '../../../../components/ui/button'; import { INITIALIZE_END_OF_FLOW_ROUTE, INITIALIZE_SEED_PHRASE_ROUTE, } from '../../../../helpers/constants/routes'; import { EVENT, EVENT_NAMES, } from '../../../../../shared/constants/metametrics'; import { exportAsFile } from '../../../../helpers/utils/export-utils'; import DraggableSeed from './draggable-seed.component'; const EMPTY_SEEDS = Array(12).fill(null); export default class ConfirmSeedPhrase extends PureComponent { static contextTypes = { trackEvent: PropTypes.func, t: PropTypes.func, }; static defaultProps = { seedPhrase: '', }; static propTypes = { history: PropTypes.object, seedPhrase: PropTypes.string, setSeedPhraseBackedUp: PropTypes.func, }; state = { selectedSeedIndices: [], sortedSeedWords: [], pendingSeedIndices: [], draggingSeedIndex: -1, hoveringIndex: -1, }; componentDidMount() { const { seedPhrase = '' } = this.props; const sortedSeedWords = (seedPhrase.split(' ') || []).sort(); this.setState({ sortedSeedWords }); } setDraggingSeedIndex = (draggingSeedIndex) => this.setState({ draggingSeedIndex }); setHoveringIndex = (hoveringIndex) => this.setState({ hoveringIndex }); onDrop = (targetIndex) => { const { selectedSeedIndices, draggingSeedIndex } = this.state; const indices = insert( selectedSeedIndices, draggingSeedIndex, targetIndex, true, ); this.setState({ selectedSeedIndices: indices, pendingSeedIndices: indices, draggingSeedIndex: -1, hoveringIndex: -1, }); }; handleExport = () => { exportAsFile('', this.props.seedPhrase, 'text/plain'); }; handleSubmit = async () => { const { history, setSeedPhraseBackedUp } = this.props; if (!this.isValid()) { return; } try { setSeedPhraseBackedUp(true).then(async () => { this.context.trackEvent({ category: EVENT.CATEGORIES.ONBOARDING, event: EVENT_NAMES.WALLET_CREATED, properties: { account_type: EVENT.ACCOUNT_TYPES.DEFAULT, is_backup_skipped: false, }, }); history.replace(INITIALIZE_END_OF_FLOW_ROUTE); }); } catch (error) { console.error(error.message); this.context.trackEvent({ category: EVENT.CATEGORIES.ONBOARDING, event: EVENT_NAMES.WALLET_SETUP_FAILED, properties: { account_type: EVENT.ACCOUNT_TYPES.DEFAULT, is_backup_skipped: false, reason: 'Seed Phrase Creation Error', error: error.message, }, }); } }; handleSelectSeedWord = (index) => { this.setState({ selectedSeedIndices: [...this.state.selectedSeedIndices, index], pendingSeedIndices: [...this.state.pendingSeedIndices, index], }); }; handleDeselectSeedWord = (index) => { this.setState({ selectedSeedIndices: this.state.selectedSeedIndices.filter( (i) => index !== i, ), pendingSeedIndices: this.state.pendingSeedIndices.filter( (i) => index !== i, ), }); }; isValid() { const { seedPhrase } = this.props; const { selectedSeedIndices, sortedSeedWords } = this.state; const selectedSeedWords = selectedSeedIndices.map( (i) => sortedSeedWords[i], ); return seedPhrase === selectedSeedWords.join(' '); } render() { const { t } = this.context; const { history } = this.props; const { selectedSeedIndices, sortedSeedWords, draggingSeedIndex } = this.state; return (
{ e.preventDefault(); history.push(INITIALIZE_SEED_PHRASE_ROUTE); }} href="#" > {`< ${t('back')}`}
{t('confirmSecretBackupPhrase')}
{t('selectEachPhrase')}
-1, })} > {this.renderPendingSeeds()} {this.renderSelectedSeeds()}
{sortedSeedWords.map((word, index) => { const isSelected = selectedSeedIndices.includes(index); return ( { if (isSelected) { this.handleDeselectSeedWord(index); } else { this.handleSelectSeedWord(index); } }} word={word} /> ); })}
); } renderSelectedSeeds() { const { sortedSeedWords, selectedSeedIndices, draggingSeedIndex } = this.state; return EMPTY_SEEDS.map((_, index) => { const seedIndex = selectedSeedIndices[index]; const word = sortedSeedWords[seedIndex]; return ( ); }); } renderPendingSeeds() { const { pendingSeedIndices, sortedSeedWords, draggingSeedIndex, hoveringIndex, } = this.state; const indices = insert( pendingSeedIndices, draggingSeedIndex, hoveringIndex, ); return EMPTY_SEEDS.map((_, index) => { const seedIndex = indices[index]; const word = sortedSeedWords[seedIndex]; return ( ); }); } } function insert(list, value, target, removeOld) { let nextList = [...list]; if (typeof list[target] === 'number') { nextList = [...list.slice(0, target), value, ...list.slice(target)]; } if (removeOld) { nextList = nextList.filter((seed, i) => { return seed !== value || i === target; }); } return nextList; }