import React, { PureComponent } from 'react' import PropTypes from 'prop-types' import classnames from 'classnames' import shuffle from 'lodash.shuffle' import Button from '../../../../components/ui/button' import { INITIALIZE_END_OF_FLOW_ROUTE, INITIALIZE_SEED_PHRASE_ROUTE, DEFAULT_ROUTE, } from '../../../../helpers/constants/routes' import { exportAsFile } from '../../../../helpers/utils/util' import DraggableSeed from './draggable-seed.component' const EMPTY_SEEDS = Array(12).fill(null) export default class ConfirmSeedPhrase extends PureComponent { static contextTypes = { metricsEvent: PropTypes.func, t: PropTypes.func, } static defaultProps = { seedPhrase: '', } static propTypes = { hideSeedPhraseBackupAfterOnboarding: PropTypes.func, history: PropTypes.object, onSubmit: PropTypes.func, seedPhrase: PropTypes.string, selectedAddress: PropTypes.string, initializeThreeBox: PropTypes.func, setSeedPhraseBackedUp: PropTypes.func, showingSeedPhraseBackupAfterOnboarding: PropTypes.bool, } state = { selectedSeedIndices: [], shuffledSeedWords: [], pendingSeedIndices: [], draggingSeedIndex: -1, hoveringIndex: -1, isDragging: false, } shouldComponentUpdate (nextProps, nextState) { const { seedPhrase } = this.props const { selectedSeedIndices, shuffledSeedWords, pendingSeedIndices, draggingSeedIndex, hoveringIndex, isDragging, } = this.state return seedPhrase !== nextProps.seedPhrase || draggingSeedIndex !== nextState.draggingSeedIndex || isDragging !== nextState.isDragging || hoveringIndex !== nextState.hoveringIndex || selectedSeedIndices.join(' ') !== nextState.selectedSeedIndices.join(' ') || shuffledSeedWords.join(' ') !== nextState.shuffledSeedWords.join(' ') || pendingSeedIndices.join(' ') !== nextState.pendingSeedIndices.join(' ') } componentDidMount () { const { seedPhrase = '' } = this.props const shuffledSeedWords = shuffle(seedPhrase.split(' ')) || [] this.setState({ shuffledSeedWords }) } 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('MetaMask Secret Backup Phrase', this.props.seedPhrase, 'text/plain') } handleSubmit = async () => { const { history, setSeedPhraseBackedUp, showingSeedPhraseBackupAfterOnboarding, hideSeedPhraseBackupAfterOnboarding, initializeThreeBox, } = this.props if (!this.isValid()) { return } try { this.context.metricsEvent({ eventOpts: { category: 'Onboarding', action: 'Seed Phrase Setup', name: 'Verify Complete', }, }) setSeedPhraseBackedUp(true).then(() => { if (showingSeedPhraseBackupAfterOnboarding) { hideSeedPhraseBackupAfterOnboarding() history.push(DEFAULT_ROUTE) } else { initializeThreeBox() history.push(INITIALIZE_END_OF_FLOW_ROUTE) } }) } catch (error) { console.error(error.message) } } handleSelectSeedWord = (shuffledIndex) => { this.setState({ selectedSeedIndices: [...this.state.selectedSeedIndices, shuffledIndex], pendingSeedIndices: [...this.state.pendingSeedIndices, shuffledIndex], }) } handleDeselectSeedWord = shuffledIndex => { this.setState({ selectedSeedIndices: this.state.selectedSeedIndices.filter(i => shuffledIndex !== i), pendingSeedIndices: this.state.pendingSeedIndices.filter(i => shuffledIndex !== i), }) } isValid () { const { seedPhrase } = this.props const { selectedSeedIndices, shuffledSeedWords } = this.state const selectedSeedWords = selectedSeedIndices.map(i => shuffledSeedWords[i]) return seedPhrase === selectedSeedWords.join(' ') } render () { const { t } = this.context const { history } = this.props const { selectedSeedIndices, shuffledSeedWords, draggingSeedIndex, } = this.state return (