[APP-655] Password autocomplete when logging in (#838)
* remove unused styles * refine login form to autofill password from password managerzio/stable
parent
8cc89a5a16
commit
bf36101bf2
|
@ -10,7 +10,7 @@ import {
|
||||||
import {observer} from 'mobx-react-lite'
|
import {observer} from 'mobx-react-lite'
|
||||||
import {useAnalytics} from 'lib/analytics'
|
import {useAnalytics} from 'lib/analytics'
|
||||||
import {Text} from '../../util/text/Text'
|
import {Text} from '../../util/text/Text'
|
||||||
import {s, colors} from 'lib/styles'
|
import {s} from 'lib/styles'
|
||||||
import {useStores} from 'state/index'
|
import {useStores} from 'state/index'
|
||||||
import {CreateAccountModel} from 'state/models/ui/create-account'
|
import {CreateAccountModel} from 'state/models/ui/create-account'
|
||||||
import {usePalette} from 'lib/hooks/usePalette'
|
import {usePalette} from 'lib/hooks/usePalette'
|
||||||
|
@ -127,118 +127,4 @@ const styles = StyleSheet.create({
|
||||||
paddingHorizontal: 20,
|
paddingHorizontal: 20,
|
||||||
paddingVertical: 20,
|
paddingVertical: 20,
|
||||||
},
|
},
|
||||||
|
|
||||||
noTopBorder: {
|
|
||||||
borderTopWidth: 0,
|
|
||||||
},
|
|
||||||
logoHero: {
|
|
||||||
paddingTop: 30,
|
|
||||||
paddingBottom: 40,
|
|
||||||
},
|
|
||||||
group: {
|
|
||||||
borderWidth: 1,
|
|
||||||
borderRadius: 10,
|
|
||||||
marginBottom: 20,
|
|
||||||
marginHorizontal: 20,
|
|
||||||
},
|
|
||||||
groupLabel: {
|
|
||||||
paddingHorizontal: 20,
|
|
||||||
paddingBottom: 5,
|
|
||||||
},
|
|
||||||
groupContent: {
|
|
||||||
borderTopWidth: 1,
|
|
||||||
flexDirection: 'row',
|
|
||||||
alignItems: 'center',
|
|
||||||
},
|
|
||||||
groupContentIcon: {
|
|
||||||
marginLeft: 10,
|
|
||||||
},
|
|
||||||
textInput: {
|
|
||||||
flex: 1,
|
|
||||||
width: '100%',
|
|
||||||
paddingVertical: 10,
|
|
||||||
paddingHorizontal: 12,
|
|
||||||
fontSize: 17,
|
|
||||||
letterSpacing: 0.25,
|
|
||||||
fontWeight: '400',
|
|
||||||
borderRadius: 10,
|
|
||||||
},
|
|
||||||
textBtn: {
|
|
||||||
flexDirection: 'row',
|
|
||||||
flex: 1,
|
|
||||||
alignItems: 'center',
|
|
||||||
},
|
|
||||||
textBtnLabel: {
|
|
||||||
flex: 1,
|
|
||||||
paddingVertical: 10,
|
|
||||||
paddingHorizontal: 12,
|
|
||||||
},
|
|
||||||
textBtnFakeInnerBtn: {
|
|
||||||
flexDirection: 'row',
|
|
||||||
alignItems: 'center',
|
|
||||||
borderRadius: 6,
|
|
||||||
paddingVertical: 6,
|
|
||||||
paddingHorizontal: 8,
|
|
||||||
marginHorizontal: 6,
|
|
||||||
},
|
|
||||||
textBtnFakeInnerBtnIcon: {
|
|
||||||
marginRight: 4,
|
|
||||||
},
|
|
||||||
picker: {
|
|
||||||
flex: 1,
|
|
||||||
width: '100%',
|
|
||||||
paddingVertical: 10,
|
|
||||||
paddingHorizontal: 12,
|
|
||||||
fontSize: 17,
|
|
||||||
borderRadius: 10,
|
|
||||||
},
|
|
||||||
pickerLabel: {
|
|
||||||
fontSize: 17,
|
|
||||||
},
|
|
||||||
checkbox: {
|
|
||||||
borderWidth: 1,
|
|
||||||
borderRadius: 2,
|
|
||||||
width: 16,
|
|
||||||
height: 16,
|
|
||||||
marginLeft: 16,
|
|
||||||
},
|
|
||||||
checkboxFilled: {
|
|
||||||
borderWidth: 1,
|
|
||||||
borderRadius: 2,
|
|
||||||
width: 16,
|
|
||||||
height: 16,
|
|
||||||
marginLeft: 16,
|
|
||||||
},
|
|
||||||
policies: {
|
|
||||||
flexDirection: 'row',
|
|
||||||
alignItems: 'flex-start',
|
|
||||||
paddingHorizontal: 20,
|
|
||||||
paddingBottom: 20,
|
|
||||||
},
|
|
||||||
error: {
|
|
||||||
backgroundColor: colors.red4,
|
|
||||||
flexDirection: 'row',
|
|
||||||
alignItems: 'center',
|
|
||||||
marginTop: -5,
|
|
||||||
marginHorizontal: 20,
|
|
||||||
marginBottom: 15,
|
|
||||||
borderRadius: 8,
|
|
||||||
paddingHorizontal: 8,
|
|
||||||
paddingVertical: 8,
|
|
||||||
},
|
|
||||||
errorFloating: {
|
|
||||||
marginBottom: 20,
|
|
||||||
marginHorizontal: 20,
|
|
||||||
borderRadius: 8,
|
|
||||||
},
|
|
||||||
errorIcon: {
|
|
||||||
borderWidth: 1,
|
|
||||||
borderColor: colors.white,
|
|
||||||
borderRadius: 30,
|
|
||||||
width: 16,
|
|
||||||
height: 16,
|
|
||||||
alignItems: 'center',
|
|
||||||
justifyContent: 'center',
|
|
||||||
marginRight: 5,
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import React, {useState, useEffect} from 'react'
|
import React, {useState, useEffect, useRef} from 'react'
|
||||||
import {
|
import {
|
||||||
ActivityIndicator,
|
ActivityIndicator,
|
||||||
Keyboard,
|
Keyboard,
|
||||||
|
@ -282,6 +282,7 @@ const LoginForm = ({
|
||||||
const [isProcessing, setIsProcessing] = useState<boolean>(false)
|
const [isProcessing, setIsProcessing] = useState<boolean>(false)
|
||||||
const [identifier, setIdentifier] = useState<string>(initialHandle)
|
const [identifier, setIdentifier] = useState<string>(initialHandle)
|
||||||
const [password, setPassword] = useState<string>('')
|
const [password, setPassword] = useState<string>('')
|
||||||
|
const passwordInputRef = useRef<TextInput>(null)
|
||||||
|
|
||||||
const onPressSelectService = () => {
|
const onPressSelectService = () => {
|
||||||
store.shell.openModal({
|
store.shell.openModal({
|
||||||
|
@ -294,6 +295,7 @@ const LoginForm = ({
|
||||||
}
|
}
|
||||||
|
|
||||||
const onPressNext = async () => {
|
const onPressNext = async () => {
|
||||||
|
Keyboard.dismiss()
|
||||||
setError('')
|
setError('')
|
||||||
setIsProcessing(true)
|
setIsProcessing(true)
|
||||||
|
|
||||||
|
@ -391,6 +393,12 @@ const LoginForm = ({
|
||||||
autoCapitalize="none"
|
autoCapitalize="none"
|
||||||
autoFocus
|
autoFocus
|
||||||
autoCorrect={false}
|
autoCorrect={false}
|
||||||
|
autoComplete="username"
|
||||||
|
returnKeyType="next"
|
||||||
|
onSubmitEditing={() => {
|
||||||
|
passwordInputRef.current?.focus()
|
||||||
|
}}
|
||||||
|
blurOnSubmit={false} // prevents flickering due to onSubmitEditing going to next field
|
||||||
keyboardAppearance={theme.colorScheme}
|
keyboardAppearance={theme.colorScheme}
|
||||||
value={identifier}
|
value={identifier}
|
||||||
onChangeText={str => setIdentifier((str || '').toLowerCase())}
|
onChangeText={str => setIdentifier((str || '').toLowerCase())}
|
||||||
|
@ -406,21 +414,23 @@ const LoginForm = ({
|
||||||
/>
|
/>
|
||||||
<TextInput
|
<TextInput
|
||||||
testID="loginPasswordInput"
|
testID="loginPasswordInput"
|
||||||
|
ref={passwordInputRef}
|
||||||
style={[pal.text, styles.textInput]}
|
style={[pal.text, styles.textInput]}
|
||||||
placeholder="Password"
|
placeholder="Password"
|
||||||
placeholderTextColor={pal.colors.textLight}
|
placeholderTextColor={pal.colors.textLight}
|
||||||
autoCapitalize="none"
|
autoCapitalize="none"
|
||||||
autoCorrect={false}
|
autoCorrect={false}
|
||||||
|
autoComplete="password"
|
||||||
|
returnKeyType="done"
|
||||||
|
enablesReturnKeyAutomatically={true}
|
||||||
keyboardAppearance={theme.colorScheme}
|
keyboardAppearance={theme.colorScheme}
|
||||||
secureTextEntry
|
secureTextEntry={true}
|
||||||
// HACK
|
textContentType="password"
|
||||||
// mitigates a known issue where the secure password prompt interferes
|
clearButtonMode="while-editing"
|
||||||
// https://github.com/facebook/react-native/issues/21911
|
|
||||||
// prf
|
|
||||||
textContentType="oneTimeCode"
|
|
||||||
value={password}
|
value={password}
|
||||||
onChangeText={setPassword}
|
onChangeText={setPassword}
|
||||||
onSubmitEditing={onPressNext}
|
onSubmitEditing={onPressNext}
|
||||||
|
blurOnSubmit={false} // HACK: https://github.com/facebook/react-native/issues/21911#issuecomment-558343069 Keyboard blur behavior is now handled in onSubmitEditing
|
||||||
editable={!isProcessing}
|
editable={!isProcessing}
|
||||||
accessibilityLabel="Password"
|
accessibilityLabel="Password"
|
||||||
accessibilityHint={
|
accessibilityHint={
|
||||||
|
|
Loading…
Reference in New Issue