diff --git a/app/components/Views/AccountBackupStep5/__snapshots__/index.test.js.snap b/app/components/Views/AccountBackupStep5/__snapshots__/index.test.js.snap index ddf90a22edf..90220a1ff5a 100644 --- a/app/components/Views/AccountBackupStep5/__snapshots__/index.test.js.snap +++ b/app/components/Views/AccountBackupStep5/__snapshots__/index.test.js.snap @@ -155,9 +155,7 @@ exports[`AccountBackupStep5 should render correctly 1`] = ` }, ] } - > - - + /> - - + /> - - + /> - - + /> - - + /> - - + /> - - + /> - - + /> - - + /> - - + /> - - + /> - - + /> @@ -519,7 +495,7 @@ exports[`AccountBackupStep5 should render correctly 1`] = ` "paddingVertical": 5, "width": 95, }, - null, + false, ] } > @@ -531,7 +507,7 @@ exports[`AccountBackupStep5 should render correctly 1`] = ` "lineHeight": 14, "textAlign": "center", }, - null, + false, ] } > @@ -557,7 +533,7 @@ exports[`AccountBackupStep5 should render correctly 1`] = ` "paddingVertical": 5, "width": 95, }, - null, + false, ] } > @@ -569,7 +545,7 @@ exports[`AccountBackupStep5 should render correctly 1`] = ` "lineHeight": 14, "textAlign": "center", }, - null, + false, ] } > @@ -595,7 +571,7 @@ exports[`AccountBackupStep5 should render correctly 1`] = ` "paddingVertical": 5, "width": 95, }, - null, + false, ] } > @@ -607,7 +583,7 @@ exports[`AccountBackupStep5 should render correctly 1`] = ` "lineHeight": 14, "textAlign": "center", }, - null, + false, ] } > @@ -633,7 +609,7 @@ exports[`AccountBackupStep5 should render correctly 1`] = ` "paddingVertical": 5, "width": 95, }, - null, + false, ] } > @@ -645,7 +621,7 @@ exports[`AccountBackupStep5 should render correctly 1`] = ` "lineHeight": 14, "textAlign": "center", }, - null, + false, ] } > @@ -671,7 +647,7 @@ exports[`AccountBackupStep5 should render correctly 1`] = ` "paddingVertical": 5, "width": 95, }, - null, + false, ] } > @@ -683,7 +659,7 @@ exports[`AccountBackupStep5 should render correctly 1`] = ` "lineHeight": 14, "textAlign": "center", }, - null, + false, ] } > @@ -709,7 +685,7 @@ exports[`AccountBackupStep5 should render correctly 1`] = ` "paddingVertical": 5, "width": 95, }, - null, + false, ] } > @@ -721,7 +697,7 @@ exports[`AccountBackupStep5 should render correctly 1`] = ` "lineHeight": 14, "textAlign": "center", }, - null, + false, ] } > @@ -747,7 +723,7 @@ exports[`AccountBackupStep5 should render correctly 1`] = ` "paddingVertical": 5, "width": 95, }, - null, + false, ] } > @@ -759,7 +735,7 @@ exports[`AccountBackupStep5 should render correctly 1`] = ` "lineHeight": 14, "textAlign": "center", }, - null, + false, ] } > @@ -785,7 +761,7 @@ exports[`AccountBackupStep5 should render correctly 1`] = ` "paddingVertical": 5, "width": 95, }, - null, + false, ] } > @@ -797,7 +773,7 @@ exports[`AccountBackupStep5 should render correctly 1`] = ` "lineHeight": 14, "textAlign": "center", }, - null, + false, ] } > @@ -823,7 +799,7 @@ exports[`AccountBackupStep5 should render correctly 1`] = ` "paddingVertical": 5, "width": 95, }, - null, + false, ] } > @@ -835,7 +811,7 @@ exports[`AccountBackupStep5 should render correctly 1`] = ` "lineHeight": 14, "textAlign": "center", }, - null, + false, ] } > @@ -861,7 +837,7 @@ exports[`AccountBackupStep5 should render correctly 1`] = ` "paddingVertical": 5, "width": 95, }, - null, + false, ] } > @@ -873,7 +849,7 @@ exports[`AccountBackupStep5 should render correctly 1`] = ` "lineHeight": 14, "textAlign": "center", }, - null, + false, ] } > @@ -899,7 +875,7 @@ exports[`AccountBackupStep5 should render correctly 1`] = ` "paddingVertical": 5, "width": 95, }, - null, + false, ] } > @@ -911,7 +887,7 @@ exports[`AccountBackupStep5 should render correctly 1`] = ` "lineHeight": 14, "textAlign": "center", }, - null, + false, ] } > @@ -937,7 +913,7 @@ exports[`AccountBackupStep5 should render correctly 1`] = ` "paddingVertical": 5, "width": 95, }, - null, + false, ] } > @@ -949,7 +925,7 @@ exports[`AccountBackupStep5 should render correctly 1`] = ` "lineHeight": 14, "textAlign": "center", }, - null, + false, ] } > diff --git a/app/components/Views/AccountBackupStep5/index.js b/app/components/Views/AccountBackupStep5/index.js index 2cc88ea478f..c56b2d56f8b 100644 --- a/app/components/Views/AccountBackupStep5/index.js +++ b/app/components/Views/AccountBackupStep5/index.js @@ -174,9 +174,64 @@ class AccountBackupStep5 extends PureComponent { } state = { - confirmedWords: Array(12).fill(), + confirmedWords: Array(12).fill({ word: undefined, originalPosition: undefined }), + showSuccessModal: false, + wordsDict: {}, currentIndex: 0, - showSuccessModal: false + seedPhraseReady: false + }; + + componentDidMount = () => { + this.createWordsDictionary(); + }; + + createWordsDictionary = () => { + const dict = {}; + this.words.forEach((word, i) => { + dict[`${word},${i}`] = { currentPosition: undefined }; + }); + this.setState({ wordsDict: dict }); + }; + + findNextAvailableIndex = () => { + const { confirmedWords } = this.state; + return confirmedWords.findIndex(({ word }) => !word); + }; + + selectWord = (word, i) => { + const { wordsDict, confirmedWords } = this.state; + let currentIndex = this.state.currentIndex; + if (wordsDict[`${word},${i}`].currentPosition !== undefined) { + currentIndex = wordsDict[`${word},${i}`].currentPosition; + wordsDict[`${word},${i}`].currentPosition = undefined; + confirmedWords[currentIndex] = { word: undefined, originalPosition: undefined }; + } else { + wordsDict[`${word},${i}`].currentPosition = currentIndex; + confirmedWords[currentIndex] = { word, originalPosition: i }; + currentIndex = this.findNextAvailableIndex(); + } + this.setState({ + currentIndex, + wordsDict, + confirmedWords, + seedPhraseReady: this.findNextAvailableIndex() === -1 + }); + }; + + clearConfirmedWordAt = i => { + const { confirmedWords, wordsDict } = this.state; + const { word, originalPosition } = confirmedWords[i]; + const currentIndex = i; + if (word && (originalPosition || originalPosition === 0)) { + wordsDict[[word, originalPosition]].currentPosition = undefined; + confirmedWords[i] = { word: undefined, originalPosition: undefined }; + } + this.setState({ + currentIndex, + wordsDict, + confirmedWords, + seedPhraseReady: this.findNextAvailableIndex() === -1 + }); }; goBack = () => { @@ -185,7 +240,8 @@ class AccountBackupStep5 extends PureComponent { goNext = () => { const words = this.props.navigation.getParam('words', []); - if (words.join('') === this.state.confirmedWords.join('')) { + const confirmedWords = this.state.confirmedWords.map(confirmedWord => confirmedWord.word); + if (words.join('') === confirmedWords.join('')) { this.props.seedphraseBackedUp(); this.setState({ showSuccessModal: true }); } else { @@ -206,85 +262,41 @@ class AccountBackupStep5 extends PureComponent { }); }; - getIndexOfWord(word, index, words) { - const confirmedWordsOcurrences = this.getNumberOfOcurrences(word, words); - if (confirmedWordsOcurrences === 1) { - return words.indexOf(word); - } - - let currentOccurence = 0; - - for (let i = 0; i < words.length; i++) { - if (words[i] === word) { - currentOccurence++; - if (i === index && currentOccurence <= confirmedWordsOcurrences) { - return i; - } - } - } - return words.indexOf(word); - } - - selectWord = (word, i) => { - const newConfirmedWords = this.state.confirmedWords.slice(); - let newIndex; - if (this.isSelectedWord(word, i)) { - const matchIndex = this.getIndexOfWord(word, i, this.state.confirmedWords); - newConfirmedWords[matchIndex] = undefined; - newIndex = matchIndex; - } else { - // Find next empty cell - newConfirmedWords[this.state.currentIndex] = word; - newIndex = 11; - for (i = this.state.currentIndex; i < 12; i++) { - if (newConfirmedWords[i] === undefined) { - newIndex = i; - break; - } - } - } - this.setState({ confirmedWords: newConfirmedWords, currentIndex: newIndex }); + renderWordBox = (word, i) => { + const { currentIndex } = this.state; + let wordText = ''; + if (word) wordText = `${i + 1}. ${word}`; + return ( + { + this.clearConfirmedWordAt(i); + }} + > + {wordText} + + ); }; - updateWordAtIndex = index => { - const newConfirmedWords = this.state.confirmedWords.slice(); - const newIndex = index; - newConfirmedWords[index] = undefined; - this.setState({ confirmedWords: newConfirmedWords, currentIndex: newIndex }); + renderWordSelectableBox = (key, i) => { + const { wordsDict } = this.state; + const [word] = key.split(','); + const selected = wordsDict[key].currentPosition !== undefined; + return ( + this.selectWord(word, i)} + style={[styles.selectableWord, selected && styles.selectedWord]} + key={`selectableWord_${i}`} + > + {word} + + ); }; - getNumberOfOcurrences(word, words) { - let ocurrences = 0; - for (let i = 0; i < words.length; i++) { - words[i] === word && ocurrences++; - } - return ocurrences; - } - - isSelectedWord(word, index) { - if (!this.state.confirmedWords.includes(word)) { - return false; - } - const totalOcurrences = this.getNumberOfOcurrences(word, this.words); - const confirmedWordsOcurrences = this.getNumberOfOcurrences(word, this.state.confirmedWords); - if (totalOcurrences === confirmedWordsOcurrences) { - return true; - } - - let currentOccurence = 0; - - for (let i = 0; i < this.words.length; i++) { - if (this.words[i] === word) { - currentOccurence++; - if (i === index && currentOccurence <= confirmedWordsOcurrences) { - return true; - } - } - } - return false; - } - - render() { + render = () => { + const { confirmedWords, wordsDict, seedPhraseReady } = this.state; return ( @@ -301,58 +313,15 @@ class AccountBackupStep5 extends PureComponent { - {this.state.confirmedWords.slice(0, 6).map((word, i) => ( - this.updateWordAtIndex(i)} - > - - {(word && `${i + 1}. ${word}`) || ' '} - - - ))} + {confirmedWords.slice(0, 6).map(({ word }, i) => this.renderWordBox(word, i))} - {this.state.confirmedWords.slice(-6).map((word, i) => ( - this.updateWordAtIndex(i + 6)} - key={`word_${i}`} - > - - {(word && `${i + 7}. ${word}`) || ' '} - - - ))} + {confirmedWords.slice(-6).map(({ word }, i) => this.renderWordBox(word, i + 6))} - {this.words.map((word, i) => { - const selected = this.isSelectedWord(word, i) ? styles.selectedWord : null; - const selectedText = selected ? styles.selectedWordText : null; - return ( - this.selectWord(word, i)} - style={[styles.selectableWord, selected]} - key={`selectableWord_${i}`} - > - {word} - - ); - })} + {Object.keys(wordsDict).map((key, i) => this.renderWordSelectableBox(key, i))} @@ -361,7 +330,7 @@ class AccountBackupStep5 extends PureComponent { type={'confirm'} onPress={this.goNext} testID={'submit-button'} - disabled={!(this.state.confirmedWords.filter(word => word === undefined).length === 0)} + disabled={!seedPhraseReady} > {strings('account_backup_step_5.cta_text')} @@ -380,7 +349,7 @@ class AccountBackupStep5 extends PureComponent { ); - } + }; } const mapDispatchToProps = dispatch => ({ diff --git a/scripts/build.sh b/scripts/build.sh index 2c8fcf9b7c5..2dfc375e724 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -175,7 +175,7 @@ buildIosRelease(){ if [ ! -f "ios/release.xcconfig" ] ; then echo "$IOS_ENV" | tr "|" "\n" > ios/release.xcconfig fi - ./node_modules/.bin/react-native run-ios --configuration Release --simulator "iPhone 11 Pro (13.2)" + ./node_modules/.bin/react-native run-ios --configuration Release --simulator "iPhone 11 Pro" fi }