Skip to content

Commit

Permalink
UI/UX for repeting 24 words (#163)
Browse files Browse the repository at this point in the history
* fix: confirm seed phrase

* fix: shuffle words

* fix: lint code

* fix: change badge styles for IOS

* fix: change styles

* fix: change colors

* Update src/ux/createKeys/new/ConfirmNewMasterKeyScreen.tsx

Co-authored-by: Ilan <36084092+ilanolkies@users.noreply.github.com>
  • Loading branch information
lucachaco and ilanolkies committed Feb 25, 2022
1 parent c484e03 commit 5e8587e
Show file tree
Hide file tree
Showing 2 changed files with 186 additions and 60 deletions.
172 changes: 112 additions & 60 deletions src/ux/createKeys/new/ConfirmNewMasterKeyScreen.tsx
Original file line number Diff line number Diff line change
@@ -1,100 +1,152 @@
import React, { useState } from 'react'
import { StyleSheet, View, ScrollView, TextInput } from 'react-native'
import { Button, Header2, Paragraph } from '../../../components'
import {
StyleSheet,
View,
ScrollView,
Text,
TouchableOpacity,
} from 'react-native'
import { CreateKeysProps, ScreenProps } from '../types'
import { useTranslation, Trans } from 'react-i18next'
import { useTranslation } from 'react-i18next'
import { grid } from '../../../styles/grid'
import { SquareButton } from '../../../components/button/SquareButton'
import { Arrow } from '../../../components/icons'
import { getTokenColor } from '../../../screens/home/tokenColor'
import { WordInput } from './WordInput'
import { colors } from '../../../styles/colors'

interface ConfirmMasterKeyScreenProps {
createFirstWallet: CreateKeysProps['createFirstWallet']
}
// source: https://stackoverflow.com/questions/63813211/qualtrics-and-javascript-randomly-insert-words-into-sentences
const shuffle = (array: string[]) => {
let currentIndex = array.length,
randomIndex

// While there remain elements to shuffle...
while (currentIndex !== 0) {
// Pick a remaining element...
randomIndex = Math.floor(Math.random() * currentIndex)
currentIndex--

// And swap it with the current element.
;[array[currentIndex], array[randomIndex]] = [
array[randomIndex],
array[currentIndex],
]
}

return array
}

export const ConfirmNewMasterKeyScreen: React.FC<
ScreenProps<'ConfirmNewMasterKey'> & ConfirmMasterKeyScreenProps
> = ({ route, navigation, createFirstWallet }) => {
const mnemonic = route.params.mnemonic
const [selectedWords, setSelectedWords] = useState<string[]>([])
const [words, setWords] = useState<string[]>(shuffle(mnemonic.split(' ')))

//TODO: create "three column grid" component
const rows = [1, 2, 3, 4, 5, 6, 7, 8]

const [mnemonicToConfirm, setMnemonicToConfirm] = useState<
string | undefined
>()
const { t } = useTranslation()

const [error, setError] = useState<string | null>(null)

const selectWord = (selectedWord: string) => {
setError(null)
const updatedWords = [...selectedWords, selectedWord]
setSelectedWords(updatedWords)
setWords(words.filter(word => !updatedWords.find(w => w === word)))
}
const saveAndNavigate = async () => {
const rifWallet = await createFirstWallet(mnemonic)
// @ts-ignore
navigation.navigate('KeysCreated', { address: rifWallet.address })
}

const handleConfirmMnemonic = async () => {
const isValid = mnemonic === mnemonicToConfirm
const isValid = mnemonic === selectedWords.join(' ')

if (!isValid) {
setError(t('entered words does not match you your master key'))
setError(t('Entered words does not match you your master key'))
return
}

await saveAndNavigate()
}

return (
<ScrollView>
<View style={styles.sectionCentered}>
<Paragraph>
<Trans>
With your master key (seed phrase) you are able to create as many
wallets as you need.
</Trans>
</Paragraph>
</View>
<View style={styles.sectionCentered}>
<Paragraph>validate your master key</Paragraph>
</View>
<View style={styles.section}>
<Header2>Master key</Header2>
<TextInput
onChangeText={text => setMnemonicToConfirm(text)}
value={mnemonicToConfirm}
placeholder={t('Enter your 12 words master key')}
multiline
style={styles.input}
testID="Input.Confirm"
/>
{error && <Paragraph>{error}</Paragraph>}
</View>
<View style={styles.section}>
<Button onPress={saveAndNavigate} title={'Skip'} />
</View>
<View style={styles.section}>
<Button
onPress={handleConfirmMnemonic}
title={'Confirm'}
testID="Button.Confirm"
/>
<ScrollView style={styles.parent}>
<Text style={styles.header}>Confirm your master key</Text>

{rows.map(row => (
<View style={grid.row}>
<WordInput wordNumber={row} initValue={selectedWords[row - 1]} />
<WordInput
wordNumber={row + rows.length}
initValue={selectedWords[row + rows.length - 1]}
/>
<WordInput
wordNumber={row + rows.length * 2}
initValue={selectedWords[row + rows.length * 2 - 1]}
/>
<Text>{row + rows.length}</Text>
</View>
))}
<View style={styles.badgeArea}>
{words.map(word => (
<View key={word} style={styles.badgeContainer}>
<TouchableOpacity
style={styles.badgeText}
onPress={() => selectWord(word)}>
<Text>{word}</Text>
</TouchableOpacity>
</View>
))}
</View>
{error && <Text style={styles.defaultText}>{error}</Text>}

<SquareButton
// @ts-ignore
onPress={handleConfirmMnemonic}
title=""
testID="Address.CopyButton"
icon={<Arrow color={getTokenColor('RBTC')} rotate={90} />}
/>
</ScrollView>
)
}

const styles = StyleSheet.create({
section: {
paddingTop: 15,
paddingBottom: 15,
borderBottomWidth: 1,
borderBottomColor: '#CCCCCC',
defaultText: {
color: colors.white,
},
parent: {
backgroundColor: colors.darkBlue,
},
sectionCentered: {
paddingTop: 15,
paddingBottom: 15,
borderBottomWidth: 1,
borderBottomColor: '#CCCCCC',
alignItems: 'center',

badgeArea: {
flexDirection: 'row',
flex: 1,
flexWrap: 'wrap',
},
badgeContainer: {
padding: 1,

marginVertical: 1,
},
input: {
height: 80,
margin: 12,
borderWidth: 1,
borderColor: '#000',
padding: 10,
textAlignVertical: 'top',
badgeText: {
backgroundColor: colors.purple,
color: colors.white,
borderRadius: 30,
paddingHorizontal: 10,
paddingVertical: 5,
},

header: {
color: colors.white,
fontSize: 22,
paddingVertical: 20,
textAlign: 'center',
},
})
74 changes: 74 additions & 0 deletions src/ux/createKeys/new/WordInput.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import React from 'react'

import { grid } from '../../../styles/grid'
import { StyleSheet, View, Text, TextInput } from 'react-native'
import { colors } from '../../../styles/colors'

export const WordInput: React.FC<{
wordNumber: number
initValue: string
}> = ({ wordNumber, initValue }) => {
return (
<View
style={{
...grid.column4,
...styles.wordContainer,
}}>
<Text style={styles.wordNumber}>{wordNumber}. </Text>
{initValue ? (
<View style={styles.wordContent}>
<Text style={styles.wordText}>{initValue}</Text>
</View>
) : (
<TextInput
key={wordNumber}
style={styles.wordInput}
value={initValue}
placeholder=""
editable={false}
/>
)}
</View>
)
}

const styles = StyleSheet.create({
wordContainer: {
alignItems: 'flex-start',
alignContent: 'flex-start',
flexDirection: 'row',
marginVertical: 4,
marginLeft: 4,
},
wordContent: {
borderRadius: 20,
backgroundColor: colors.darkPurple2,
alignItems: 'flex-start',
justifyContent: 'flex-start',
paddingHorizontal: 10,
paddingVertical: 4,
marginLeft: 10,
},
wordText: {
color: colors.white,
fontSize: 14,
},
wordNumber: {
color: colors.white,
display: 'flex',
paddingVertical: 4,
},
wordInput: {
borderColor: colors.white,
borderWidth: 1,
marginHorizontal: 10,
borderRadius: 10,
flex: 1,
textAlignVertical: 'top',
paddingTop: 0,
paddingBottom: 0,
height: 25,
color: colors.white,
fontSize: 15,
},
})

0 comments on commit 5e8587e

Please sign in to comment.