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

Anthony toggle show password #4746

Closed
Closed
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
49db630
added icon button
anthony-hull Aug 16, 2021
e0e5e7b
secure input toggleable
anthony-hull Aug 17, 2021
19c8bf4
defaults password to be visible on native apps
anthony-hull Aug 17, 2021
1a55353
styling of icon
anthony-hull Aug 18, 2021
b3bf88b
lintfix
anthony-hull Aug 18, 2021
ce21ba9
fix padding where no label
anthony-hull Aug 18, 2021
e6e57ad
remove confirm password input
anthony-hull Aug 18, 2021
99a9e84
added icon button
anthony-hull Aug 16, 2021
c0090e9
secure input toggleable
anthony-hull Aug 17, 2021
815eb41
defaults password to be visible on native apps
anthony-hull Aug 17, 2021
d3783cd
styling of icon
anthony-hull Aug 18, 2021
ee51030
lintfix
anthony-hull Aug 18, 2021
aeab071
fix padding where no label
anthony-hull Aug 18, 2021
8966adc
remove confirm password input
anthony-hull Aug 18, 2021
a75412c
Merge remote-tracking branch 'anthony-hull/anthony--toggle-show-passw…
anthony-hull Aug 18, 2021
dd6bd37
merge main
anthony-hull Aug 31, 2021
9c16ede
Revert removal of confirm password inputs
anthony-hull Sep 6, 2021
bcc6e11
remove native icon in edge
anthony-hull Sep 6, 2021
13cfa13
move web only edge css to web index.html
anthony-hull Sep 13, 2021
1e62010
revert language changes
anthony-hull Sep 13, 2021
85e6bfa
remove default show on mobile
anthony-hull Sep 15, 2021
65479d2
Merge branch 'main' into anthony--toggle-show-password
anthony-hull Sep 22, 2021
2afa33b
WIP move machines
anthony-hull Sep 27, 2021
a5051ef
merge main
anthony-hull Oct 4, 2021
9ce2e36
resolve PR comments
anthony-hull Oct 20, 2021
100f3ae
merge main
anthony-hull Oct 20, 2021
5e72501
Merge branch 'main' into anthony--toggle-show-password
anthony-hull Oct 25, 2021
1024af1
fix styling
anthony-hull Oct 25, 2021
16693d9
fix element overflow
anthony-hull Oct 27, 2021
363f2cd
invert iconography for show/hide state
anthony-hull Oct 27, 2021
8825227
merge main
anthony-hull Nov 22, 2021
d799392
Merge branch 'main' into anthony--toggle-show-password
anthony-hull Nov 24, 2021
4620d0d
fixed stylings
anthony-hull Nov 24, 2021
98714a6
removed width property
anthony-hull Nov 24, 2021
b0a3419
move icon to the left
anthony-hull Nov 24, 2021
74c9978
Merge branch 'main' into anthony--toggle-show-password
anthony-hull Nov 25, 2021
ce11d2f
fix merge issues
anthony-hull Nov 25, 2021
c00c335
WIP: move machines
anthony-hull Nov 25, 2021
cfad816
fix overflow and refactor negative margin
anthony-hull Nov 29, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions assets/images/eye-disabled.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
67 changes: 51 additions & 16 deletions src/components/ExpensiTextInput/BaseExpensiTextInput.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
import React, {Component} from 'react';
import {
Animated, TextInput, View, TouchableWithoutFeedback,
Animated, TextInput, View, TouchableWithoutFeedback, Pressable,
} from 'react-native';
import Str from 'expensify-common/lib/str';
import ExpensiTextInputLabel from './ExpensiTextInputLabel';
import {propTypes, defaultProps} from './propTypes';
import themeColors from '../../styles/themes/default';
import styles from '../../styles/styles';
import styles, {getIconFillColor} from '../../styles/styles';
import Icon from '../Icon';
import {
Eye,
EyeDisabled,
} from '../Icon/Expensicons';
import getButtonState from '../../libs/getButtonState';

const ACTIVE_LABEL_TRANSLATE_Y = -10;
const ACTIVE_LABEL_TRANSLATE_X = (translateX = -22) => translateX;
Expand All @@ -28,6 +34,7 @@ class BaseExpensiTextInput extends Component {
labelTranslateX: new Animated.Value(hasValue
? ACTIVE_LABEL_TRANSLATE_X(props.translateX) : INACTIVE_LABEL_TRANSLATE_X),
labelScale: new Animated.Value(hasValue ? ACTIVE_LABEL_SCALE : INACTIVE_LABEL_SCALE),
passwordHidden: props.defaultHidePassword && props.secureTextEntry,
};

this.input = null;
Expand All @@ -36,6 +43,7 @@ class BaseExpensiTextInput extends Component {
this.onFocus = this.onFocus.bind(this);
this.onBlur = this.onBlur.bind(this);
this.setValue = this.setValue.bind(this);
this.secureTextEntry = props.secureTextEntry;
anthony-hull marked this conversation as resolved.
Show resolved Hide resolved
}

componentDidMount() {
Expand Down Expand Up @@ -107,6 +115,11 @@ class BaseExpensiTextInput extends Component {
]).start();
}

togglePasswordVisibility() {
this.setState(prevState => ({passwordHidden: !prevState.passwordHidden}));
}


anthony-hull marked this conversation as resolved.
Show resolved Hide resolved
render() {
const {
label,
Expand All @@ -118,6 +131,7 @@ class BaseExpensiTextInput extends Component {
ignoreLabelTranslateX,
innerRef,
autoFocus,
secureTextEntry,
...inputProps
} = this.props;

Expand Down Expand Up @@ -145,22 +159,43 @@ class BaseExpensiTextInput extends Component {
labelScale={this.state.labelScale}
/>
) : null}
<TextInput
ref={(ref) => {
if (typeof innerRef === 'function') { innerRef(ref); }
this.input = ref;
}}
<View style={styles.flexRow}>
<TextInput
ref={(ref) => {
if (typeof innerRef === 'function') { innerRef(ref); }
this.input = ref;
}}
// eslint-disable-next-line
{...inputProps}
value={value}
placeholder={(this.state.isFocused || !label) ? placeholder : null}
placeholderTextColor={themeColors.placeholderText}
underlineColorAndroid="transparent"
style={inputStyle}
onFocus={this.onFocus}
onBlur={this.onBlur}
onChangeText={this.setValue}
/>
value={value}
placeholder={(this.state.isFocused || !label) ? placeholder : null}
placeholderTextColor={themeColors.placeholderText}
underlineColorAndroid="transparent"
style={[...inputStyle, styles.flex1, styles.pt3, !hasLabel && styles.pv0]}
onFocus={this.onFocus}
onBlur={this.onBlur}
onChangeText={this.setValue}
secureTextEntry={this.state.passwordHidden}
/>
{secureTextEntry && (
<Pressable
accessibilityRole="button"
// eslint-disable-next-line lines-around-comment
// accessibilityLabel={this.props.translate('sidebarScreen.buttonSearch')}
anthony-hull marked this conversation as resolved.
Show resolved Hide resolved
style={[
styles.secureInputEyeButton,
]}
onPress={() => this.togglePasswordVisibility()}
>
{({hovered, pressed}) => (
<Icon
src={this.state.passwordHidden ? EyeDisabled : Eye}
fill={getIconFillColor(getButtonState(hovered, pressed))}
/>
)}
</Pressable>
)}
</View>
</View>
</TouchableWithoutFeedback>
</View>
Expand Down
1 change: 1 addition & 0 deletions src/components/ExpensiTextInput/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const ExpensiTextInput = forwardRef((props, ref) => (
innerRef={ref}
inputStyle={[styles.expensiTextInput, styles.expensiTextInputDesktop]}
ignoreLabelTranslateX
defaultHidePassword
/>
));

Expand Down
2 changes: 2 additions & 0 deletions src/components/Icon/Expensicons.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import Download from '../../../assets/images/download.svg';
import Emoji from '../../../assets/images/emoji.svg';
import Exclamation from '../../../assets/images/exclamation.svg';
import Eye from '../../../assets/images/eye.svg';
import EyeDisabled from '../../../assets/images/eye-disabled.svg';
import ExpensifyCard from '../../../assets/images/expensifycard.svg';
import Gallery from '../../../assets/images/gallery.svg';
import Gear from '../../../assets/images/gear.svg';
Expand Down Expand Up @@ -74,6 +75,7 @@ export {
Emoji,
Exclamation,
Eye,
EyeDisabled,
ExpensifyCard,
Gallery,
Gear,
Expand Down
3 changes: 0 additions & 3 deletions src/languages/en.js
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,6 @@ export default {
currentPassword: 'Current Password',
newPassword: 'New Password',
newPasswordPrompt: 'New password must be different than your old password, have at least 8 characters,\n1 capital letter, 1 lowercase letter, 1 number.',
confirmNewPassword: 'Confirm New Password',
},
addPayPalMePage: {
enterYourUsernameToGetPaidViaPayPal: 'Enter your username to get paid back via PayPal.',
Expand Down Expand Up @@ -345,9 +344,7 @@ export default {
},
setPasswordPage: {
enterPassword: 'Enter a password',
confirmNewPassword: 'Confirm the password',
setPassword: 'Set Password',
passwordsDontMatch: 'Passwords must match',
newPasswordPrompt: 'Your password must have at least 8 characters,\n1 capital letter, 1 lowercase letter, 1 number.',
passwordFormTitle: 'Welcome back to the New Expensify! Please set your password.',
},
Expand Down
3 changes: 0 additions & 3 deletions src/languages/es.js
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,6 @@ export default {
currentPassword: 'Contraseña Actual',
newPassword: 'Nueva contraseña',
newPasswordPrompt: 'La nueva contraseña tiene que ser diferente de la antigua, tener al menos 8 letras,\n1 letra mayúscula, 1 letra minúscula y 1 número.',
confirmNewPassword: 'Confirma la Nueva Contraseña',
},
addPayPalMePage: {
enterYourUsernameToGetPaidViaPayPal: 'Escribe tu nombre de usuario para que otros puedan pagarte a través de PayPal.',
Expand Down Expand Up @@ -345,9 +344,7 @@ export default {
},
setPasswordPage: {
enterPassword: 'Escribe una contraseña',
confirmNewPassword: 'Confirma la contraseña',
setPassword: 'Configura tu Contraseña',
passwordsDontMatch: 'Las contraseñas deben coincidir',
newPasswordPrompt: 'Su contraseña debe tener al menos 8 caracteres, \n1 letra mayúscula, 1 letra minúscula, 1 número.',
passwordFormTitle: '¡Bienvenido de vuelta al Nuevo Expensify! Por favor, elige una contraseña.',
},
Expand Down
52 changes: 5 additions & 47 deletions src/pages/settings/NewPasswordForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,14 @@ class NewPasswordForm extends React.Component {
super(props);

this.state = {
confirmNewPassword: '',
passwordHintError: false,
shouldShowPasswordConfirmError: false,
};
}

componentDidUpdate(prevProps, prevState) {
const eitherPasswordChanged = (this.props.password !== prevProps.password)
|| this.state.confirmNewPassword !== prevState.confirmNewPassword;
if (eitherPasswordChanged) {
this.props.updateIsFormValid(this.isValidForm());
componentDidUpdate(prevProps) {
const passwordChanged = (this.props.password !== prevProps.password);
if (passwordChanged) {
this.props.updateIsFormValid(this.isValidPassword());
}
}

Expand All @@ -52,34 +49,11 @@ class NewPasswordForm extends React.Component {
}
}

onBlurConfirmPassword() {
if (this.state.shouldShowPasswordConfirmError) {
return;
}
if (this.state.confirmNewPassword && !this.doPasswordsMatch()) {
this.setState({shouldShowPasswordConfirmError: true});
}
}

isValidPassword() {
return this.props.password.match(CONST.PASSWORD_COMPLEXITY_REGEX_STRING);
}

doPasswordsMatch() {
return this.props.password === this.state.confirmNewPassword;
}

isValidForm() {
return this.isValidPassword() && this.doPasswordsMatch();
}

showPasswordMatchError() {
return Boolean(
!this.doPasswordsMatch()
&& this.state.shouldShowPasswordConfirmError
&& this.state.confirmNewPassword,
);
}

render() {
let passwordHintStyle;
Expand All @@ -100,29 +74,13 @@ class NewPasswordForm extends React.Component {
textContentType="password"
value={this.props.password}
onChangeText={password => this.props.updatePassword(password)}
onSubmitEditing={() => this.props.onSubmitEditing()}
onBlur={() => this.onBlurNewPassword()}
/>
<Text style={[styles.textLabelSupporting, styles.mt1, passwordHintStyle]}>
{this.props.translate('setPasswordPage.newPasswordPrompt')}
</Text>
</View>
<View style={styles.mb6}>
<ExpensiTextInput
label={`${this.props.translate('setPasswordPage.confirmNewPassword')}*`}
secureTextEntry
autoCompleteType="password"
textContentType="password"
value={this.state.confirmNewPassword}
onChangeText={confirmNewPassword => this.setState({confirmNewPassword})}
onSubmitEditing={() => this.props.onSubmitEditing()}
onBlur={() => this.onBlurConfirmPassword()}
/>
{this.showPasswordMatchError() && (
<Text style={[styles.formError, styles.mt1]}>
{this.props.translate('setPasswordPage.passwordsDontMatch')}
</Text>
)}
</View>
</>
);
}
Expand Down
48 changes: 4 additions & 44 deletions src/pages/settings/PasswordPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ class PasswordPage extends Component {
this.state = {
currentPassword: '',
newPassword: '',
confirmNewPassword: '',
isPasswordRequirementsVisible: false,
shouldShowPasswordConfirmError: false,
};
Expand All @@ -62,29 +61,11 @@ class PasswordPage extends Component {
}

onBlurNewPassword() {
const stateToUpdate = {};
if (!this.state.newPassword || !this.isValidPassword()) {
stateToUpdate.isPasswordRequirementsVisible = true;
} else {
stateToUpdate.isPasswordRequirementsVisible = false;
}

if (this.state.newPassword && this.state.confirmNewPassword && !this.doPasswordsMatch()) {
stateToUpdate.shouldShowPasswordConfirmError = true;
} else {
stateToUpdate.shouldShowPasswordConfirmError = false;
}

this.setState(stateToUpdate);
this.setState(prevState => (
{isPasswordRequirementsVisible: !prevState.newPassword || !this.isValidPassword()}
));
}

onBlurConfirmPassword() {
if ((this.state.newPassword && !this.state.confirmNewPassword) || !this.doPasswordsMatch()) {
this.setState({shouldShowPasswordConfirmError: true});
} else {
this.setState({shouldShowPasswordConfirmError: false});
}
}

isValidPassword() {
return this.state.newPassword.match(CONST.PASSWORD_COMPLEXITY_REGEX_STRING);
Expand All @@ -100,9 +81,6 @@ class PasswordPage extends Component {
});
}

doPasswordsMatch() {
return this.state.newPassword === this.state.confirmNewPassword;
}

render() {
return (
Expand Down Expand Up @@ -143,6 +121,7 @@ class PasswordPage extends Component {
textContentType="password"
value={this.state.newPassword}
onChangeText={newPassword => this.setState({newPassword})}
onSubmitEditing={this.handleChangePassword}
onFocus={() => this.setState({isPasswordRequirementsVisible: true})}
onBlur={() => this.onBlurNewPassword()}
/>
Expand All @@ -152,36 +131,17 @@ class PasswordPage extends Component {
</Text>
)}
</View>
<View style={styles.mb6}>
<ExpensiTextInput
label={`${this.props.translate('passwordPage.confirmNewPassword')}*`}
secureTextEntry
autoCompleteType="password"
textContentType="password"
value={this.state.confirmNewPassword}
onChangeText={confirmNewPassword => this.setState({confirmNewPassword})}
onSubmitEditing={this.handleChangePassword}
onBlur={() => this.onBlurConfirmPassword()}
/>
</View>
{!this.state.shouldShowPasswordConfirmError && !isEmpty(this.props.account.error) && (
<Text style={styles.formError}>
{this.props.account.error}
</Text>
)}
{this.state.shouldShowPasswordConfirmError && (
<Text style={[styles.formError, styles.mt1]}>
{this.props.translate('setPasswordPage.passwordsDontMatch')}
</Text>
)}
</ScrollView>
<FixedFooter style={[styles.flexGrow0]}>
<Button
success
style={[styles.mb2]}
isDisabled={!this.state.currentPassword || !this.state.newPassword
|| !this.state.confirmNewPassword
|| (this.state.newPassword !== this.state.confirmNewPassword)
|| (this.state.currentPassword === this.state.newPassword)
|| !this.state.newPassword.match(CONST.PASSWORD_COMPLEXITY_REGEX_STRING)}
isLoading={this.props.account.loading}
Expand Down
10 changes: 9 additions & 1 deletion src/styles/styles.js
Original file line number Diff line number Diff line change
Expand Up @@ -513,7 +513,7 @@ const styles = {
borderWidth: 1,
borderRadius: variables.componentBorderRadiusNormal,
borderColor: themeColors.border,
paddingTop: 25,
anthony-hull marked this conversation as resolved.
Show resolved Hide resolved
paddingTop: 12,
paddingBottom: 8,
paddingHorizontal: 12,
justifyContent: 'center',
Expand Down Expand Up @@ -548,6 +548,14 @@ const styles = {
padding: 0,
left,
}),
secureInputEyeButton: {
right: 0,
top: 0,
borderRadius: 6,
anthony-hull marked this conversation as resolved.
Show resolved Hide resolved
height: 32,
margin: 3,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't feel good about using the margin. Can we achieve this using padding?

justifyContent: 'center',
},
textInput: {
backgroundColor: themeColors.componentBG,
borderRadius: variables.componentBorderRadiusNormal,
Expand Down