Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(wallet-mobile): display native kb for device pin #3653

Draft
wants to merge 12 commits into
base: develop
Choose a base branch
from
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react'
import React, {useEffect} from 'react'
import {defineMessages, useIntl} from 'react-intl'
rahulnr7 marked this conversation as resolved.
Show resolved Hide resolved

import {showErrorDialog} from '../../../kernel/dialogs'
Expand All @@ -25,6 +25,16 @@ export const CreatePinInput = ({onDone}: Props) => {
const [pin, setPin] = React.useState('')
const [step, setStep] = React.useState<'pin' | 'pinConfirmation'>('pin')

useEffect(() => {
if (step === 'pin') {
rahulnr7 marked this conversation as resolved.
Show resolved Hide resolved
pinInputRef.current?.clear()
pinInputRef.current?.focus()
} else if (step === 'pinConfirmation') {
pinConfirmationInputRef.current?.clear()
pinConfirmationInputRef.current?.focus()
}
}, [step])

const onPinInput = (pin: string) => {
setPin(pin)
setStep('pinConfirmation')
Expand Down
66 changes: 50 additions & 16 deletions apps/wallet-mobile/src/features/Auth/PinInput/PinInput.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import {useTheme} from '@yoroi/theme'
import _ from 'lodash'
import React from 'react'
import {StyleSheet, View} from 'react-native'
import React, {useEffect, useRef} from 'react'
rahulnr7 marked this conversation as resolved.
Show resolved Hide resolved
rahulnr7 marked this conversation as resolved.
Show resolved Hide resolved
import {StyleSheet, TextInput, View} from 'react-native'
import {InteractionManager} from 'react-native'

import {BACKSPACE, NumericKeyboard} from '../../../components/NumericKeyboard'
import {Spacer} from '../../../components/Spacer/Spacer'
import {Text} from '../../../components/Text'

Expand All @@ -18,35 +18,52 @@ type Props = {

export type PinInputRef = {
clear: () => void
focus: () => void
}

export const PinInput = React.forwardRef<PinInputRef, Props>((props, ref) => {
const {enabled = true, pinMaxLength, title, subtitles = [], onDone, onGoBack} = props
const {enabled = true, pinMaxLength, title, subtitles = [], onDone} = props
const styles = useStyles()

const [pin, setPin] = React.useState('')
const inputRef = useRef<TextInput>(null)
rahulnr7 marked this conversation as resolved.
Show resolved Hide resolved
const {isDark} = useTheme()

useEffect(() => {
rahulnr7 marked this conversation as resolved.
Show resolved Hide resolved
rahulnr7 marked this conversation as resolved.
Show resolved Hide resolved
if (enabled) {
const interaction = InteractionManager.runAfterInteractions(() => {
const timer = setTimeout(() => {
inputRef.current?.focus()
}, 300)
return () => clearTimeout(timer)
})
return () => interaction.cancel()
}
}, [enabled])

React.useImperativeHandle(ref, () => ({
clear: () => {
setPin('')
inputRef.current?.clear()
inputRef.current?.focus()
},
focus: () => {
inputRef.current?.focus()
},
}))

const onKeyDown = (value: string) => {
const handleTextChange = (value: string) => {
if (!enabled) return
if (value === BACKSPACE) {
if (pin.length === 0) onGoBack?.()
setPin(pin.substring(0, pin.length - 1))
return
}

if (pin.length === pinMaxLength) {
return
if (value.length > pinMaxLength) {
value = value.substring(0, pinMaxLength)
}

const newPin = pin.concat(value)
setPin(newPin)
if (newPin.length === pinMaxLength) onDone(newPin)
setPin(value)

if (value.length === pinMaxLength) {
onDone(value)
}
}

return (
Expand All @@ -71,7 +88,18 @@ export const PinInput = React.forwardRef<PinInputRef, Props>((props, ref) => {
</View>
</View>

<NumericKeyboard onKeyDown={onKeyDown} />
<TextInput
ref={inputRef}
style={styles.hiddenInput}
keyboardType="numeric"
value={pin}
onChangeText={handleTextChange}
maxLength={pinMaxLength}
autoFocus={true}
caretHidden={true}
importantForAccessibility="no"
keyboardAppearance={isDark ? 'dark' : 'light'}
/>
</View>
)
})
Expand Down Expand Up @@ -136,6 +164,12 @@ const useStyles = () => {
pinCircleActive: {
backgroundColor: color.primary_600,
},
hiddenInput: {
position: 'absolute',
rahulnr7 marked this conversation as resolved.
Show resolved Hide resolved
opacity: 0,
height: 0,
width: 0,
},
})
return styles
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,59 +4,59 @@
"defaultMessage": "!!!Enter PIN",
"file": "src/features/Auth/CreatePinInput/CreatePinInput.tsx",
"start": {
"line": 78,
"line": 88,
"column": 17,
"index": 2443
"index": 2731
},
"end": {
"line": 81,
"line": 91,
"column": 3,
"index": 2551
"index": 2839
}
},
{
"id": "components.initialization.custompinscreen.pinInputSubtitle",
"defaultMessage": "!!!Choose a new PIN to quickly access your wallet",
"file": "src/features/Auth/CreatePinInput/CreatePinInput.tsx",
"start": {
"line": 82,
"line": 92,
"column": 20,
"index": 2573
"index": 2861
},
"end": {
"line": 85,
"line": 95,
"column": 3,
"index": 2721
"index": 3009
}
},
{
"id": "components.initialization.custompinscreen.pinConfirmationTitle",
"defaultMessage": "!!!Repeat PIN",
"file": "src/features/Auth/CreatePinInput/CreatePinInput.tsx",
"start": {
"line": 86,
"line": 96,
"column": 29,
"index": 2752
"index": 3040
},
"end": {
"line": 89,
"line": 99,
"column": 3,
"index": 2868
"index": 3156
}
},
{
"id": "components.firstrun.custompinscreen.pinInputConfirmationSubTitle",
"defaultMessage": "!!!Repeat a new PIN to quickly access your wallet",
"file": "src/features/Auth/CreatePinInput/CreatePinInput.tsx",
"start": {
"line": 90,
"line": 100,
"column": 32,
"index": 2902
"index": 3190
},
"end": {
"line": 93,
"line": 103,
"column": 3,
"index": 3056
"index": 3344
}
}
]
Loading