From 0e31cdbf3b8b87ad3692e1d75310a19d13f5fb8a Mon Sep 17 00:00:00 2001 From: owencraston Date: Fri, 13 May 2022 13:42:14 -0400 Subject: [PATCH 01/17] Hide remember me - remove remember me from login options by default - allow users to enable it in security settings - remember me is lower priority than biometrics and biometrics will allways show up if it is enabled --- android/.project | 11 +++ .../org.eclipse.buildship.core.prefs | 11 +++ app/actions/security/index.ts | 20 ++++ app/actions/security/state.ts | 3 + app/actions/user/index.js | 7 ++ .../LoginOptionsSwitch.test.tsx | 37 +++++++ .../LoginOptionsSwitch/LoginOptionsSwitch.tsx | 97 +++++++++++++++++++ .../LoginOptionsSwitch.test.tsx.snap | 9 ++ app/components/UI/LoginOptionsSwitch/index.ts | 2 + .../UI/LoginOptionsSwitch/styles.ts | 27 ++++++ app/components/Views/ChoosePassword/index.js | 58 +++-------- app/components/Views/ImportFromSeed/index.js | 55 ++--------- app/components/Views/Login/index.js | 84 ++++++++-------- app/components/Views/ResetPassword/index.js | 64 +++--------- .../__snapshots__/index.test.tsx.snap | 2 + .../SecurityOptionToggle.tsx | 59 +++++++++++ .../components/SecurityOptionToggle/index.ts | 2 + .../components/SecurityOptionToggle/styles.ts | 32 ++++++ .../SecuritySettings/components/index.ts | 2 + .../Views/Settings/SecuritySettings/index.js | 27 ++++++ .../Settings/SecuritySettings/index.test.tsx | 3 + app/constants/test-ids.js | 17 ++++ app/reducers/index.js | 2 + app/reducers/security/index.ts | 26 +++++ app/reducers/user/index.js | 6 ++ app/util/testSetup.js | 21 +++- ios/Podfile.lock | 2 +- locales/languages/en.json | 4 + 28 files changed, 495 insertions(+), 195 deletions(-) create mode 100644 app/actions/security/index.ts create mode 100644 app/actions/security/state.ts create mode 100644 app/components/UI/LoginOptionsSwitch/LoginOptionsSwitch.test.tsx create mode 100644 app/components/UI/LoginOptionsSwitch/LoginOptionsSwitch.tsx create mode 100644 app/components/UI/LoginOptionsSwitch/__snapshots__/LoginOptionsSwitch.test.tsx.snap create mode 100644 app/components/UI/LoginOptionsSwitch/index.ts create mode 100644 app/components/UI/LoginOptionsSwitch/styles.ts create mode 100644 app/components/Views/Settings/SecuritySettings/components/SecurityOptionToggle/SecurityOptionToggle.tsx create mode 100644 app/components/Views/Settings/SecuritySettings/components/SecurityOptionToggle/index.ts create mode 100644 app/components/Views/Settings/SecuritySettings/components/SecurityOptionToggle/styles.ts create mode 100644 app/components/Views/Settings/SecuritySettings/components/index.ts create mode 100644 app/reducers/security/index.ts diff --git a/android/.project b/android/.project index 3cf8618bf4c..649ee92486f 100644 --- a/android/.project +++ b/android/.project @@ -14,4 +14,15 @@ org.eclipse.buildship.core.gradleprojectnature + + + 1659034298708 + + 30 + + org.eclipse.core.resources.regexFilterMatcher + node_modules|.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ + + + diff --git a/android/.settings/org.eclipse.buildship.core.prefs b/android/.settings/org.eclipse.buildship.core.prefs index e8895216fd3..61544433b64 100644 --- a/android/.settings/org.eclipse.buildship.core.prefs +++ b/android/.settings/org.eclipse.buildship.core.prefs @@ -1,2 +1,13 @@ +arguments= +auto.sync=false +build.scans.enabled=false +connection.gradle.distribution=GRADLE_DISTRIBUTION(WRAPPER) connection.project.dir= eclipse.preferences.version=1 +gradle.user.home= +java.home=/Library/Java/JavaVirtualMachines/zulu-11.jdk/Contents/Home +jvm.arguments= +offline.mode=false +override.workspace.settings=true +show.console.view=true +show.executions.view=true diff --git a/app/actions/security/index.ts b/app/actions/security/index.ts new file mode 100644 index 00000000000..c62bf08e450 --- /dev/null +++ b/app/actions/security/index.ts @@ -0,0 +1,20 @@ +/* eslint-disable import/prefer-default-export */ +import type { Action } from 'redux'; + +export enum ActionType { + SET_ALLOW_LOGIN_WITH_REMEMBER_ME = 'SET_ALLOW_LOGIN_WITH_REMEMBER_ME', +} + +export interface AllowLoginWithRememberMeUpdated + extends Action { + enabled: boolean; +} + +export type Action = AllowLoginWithRememberMeUpdated; + +export const setAllowLoginWithRememberMe = ( + enabled: boolean, +): AllowLoginWithRememberMeUpdated => ({ + type: ActionType.SET_ALLOW_LOGIN_WITH_REMEMBER_ME, + enabled, +}); diff --git a/app/actions/security/state.ts b/app/actions/security/state.ts new file mode 100644 index 00000000000..bf5abaf43e3 --- /dev/null +++ b/app/actions/security/state.ts @@ -0,0 +1,3 @@ +export interface SecuritySettingsState { + allowLoginWithRememberMe: boolean; +} diff --git a/app/actions/user/index.js b/app/actions/user/index.js index 3919fb17355..06fa45a5958 100644 --- a/app/actions/user/index.js +++ b/app/actions/user/index.js @@ -104,3 +104,10 @@ export function checkedAuth(initialScreen) { }, }; } + +export function setIsUsingRememberMe(isUsingRememberMe) { + return { + type: 'SET_IS_USING_REMEMBER_ME', + payload: { isUsingRememberMe }, + }; +} diff --git a/app/components/UI/LoginOptionsSwitch/LoginOptionsSwitch.test.tsx b/app/components/UI/LoginOptionsSwitch/LoginOptionsSwitch.test.tsx new file mode 100644 index 00000000000..c4629b087ef --- /dev/null +++ b/app/components/UI/LoginOptionsSwitch/LoginOptionsSwitch.test.tsx @@ -0,0 +1,37 @@ +import React from 'react'; +import { shallow } from 'enzyme'; +import LoginOptionsSwitch from './LoginOptionsSwitch'; +import { BIOMETRY_TYPE } from 'react-native-keychain'; +import { Provider } from 'react-redux'; +import configureMockStore from 'redux-mock-store'; +describe('LoginWithBiometricsSwitch', () => { + const mockStore = configureMockStore(); + // eslint-disable-next-line @typescript-eslint/no-empty-function + const handleUpdate = (_biometricsEnabled: boolean) => {}; + it('should render correctly', () => { + const store = mockStore({}); + const wrapper = shallow( + + + , + ); + expect(wrapper).toMatchSnapshot(); + }); + + it('should return empty object when shouldRenderBiometricOption is undefined and allowLoginWithRememberMe is false in settings', () => { + const store = mockStore({}); + const wrapper = shallow( + + + , + ); + expect(wrapper).toMatchObject({}); + }); +}); diff --git a/app/components/UI/LoginOptionsSwitch/LoginOptionsSwitch.tsx b/app/components/UI/LoginOptionsSwitch/LoginOptionsSwitch.tsx new file mode 100644 index 00000000000..ee54594836c --- /dev/null +++ b/app/components/UI/LoginOptionsSwitch/LoginOptionsSwitch.tsx @@ -0,0 +1,97 @@ +import React, { useCallback, useState } from 'react'; +import { View, Switch, Text } from 'react-native'; +import { mockTheme, useAppThemeFromContext } from '../../../util/theme'; +import { strings } from '../../../../locales/i18n'; +import { BIOMETRY_TYPE } from 'react-native-keychain'; +import { createStyles } from './styles'; +import { + LOGIN_WITH_BIOMETRICS_SWITCH, + LOGIN_WITH_REMEMBER_ME_SWITCH, +} from '../../../constants/test-ids'; +import { useSelector } from 'react-redux'; + +interface Props { + shouldRenderBiometricOption: BIOMETRY_TYPE | null; + onUpdateBiometryChoice: (biometryEnabled: boolean) => void; + onUpdateRememberMe: (rememberMeEnabled: boolean) => void; +} + +/** + * View that renders the toggle for login options + * The highest priority login option is biometrics and will always get rendered over other options IF it is enabled. + * If the user has enabled login with remember me in settings and has turned off biometrics then remember me will be the option + * If both of these features are disabled then no options will be rendered + */ +const LoginOptionsSwitch = ({ + shouldRenderBiometricOption, + onUpdateBiometryChoice, + onUpdateRememberMe, +}: Props) => { + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); + const allowLoginWithRememberMe = useSelector( + (state: any) => state.security.allowLoginWithRememberMe, + ); + const [biometryEnabled, setBiometryEnabled] = useState(false); + const [rememberMeEnabled, setRememberMeEnabled] = useState(false); + + const onBiometryValueChanged = useCallback(async () => { + onUpdateBiometryChoice(!biometryEnabled); + setBiometryEnabled(!biometryEnabled); + }, [biometryEnabled, onUpdateBiometryChoice]); + + const onRememberMeValueChanged = useCallback(async () => { + onUpdateRememberMe(!rememberMeEnabled); + setRememberMeEnabled(!rememberMeEnabled); + }, [onUpdateRememberMe, rememberMeEnabled]); + + // should only render remember me option if biometrics are disabled and rememberOptionMeEnabled is enabled in security settings + // if both are disabled then this component returns null + if (shouldRenderBiometricOption !== null) { + return ( + + + {strings( + `biometrics.enable_${shouldRenderBiometricOption.toLowerCase()}`, + )} + + + + ); + } else if ( + shouldRenderBiometricOption === null && + allowLoginWithRememberMe === true + ) { + return ( + + + {strings(`choose_password.remember_me`)} + + + + ); + } + return null; +}; + +export default React.memo(LoginOptionsSwitch); diff --git a/app/components/UI/LoginOptionsSwitch/__snapshots__/LoginOptionsSwitch.test.tsx.snap b/app/components/UI/LoginOptionsSwitch/__snapshots__/LoginOptionsSwitch.test.tsx.snap new file mode 100644 index 00000000000..a274ea0fa67 --- /dev/null +++ b/app/components/UI/LoginOptionsSwitch/__snapshots__/LoginOptionsSwitch.test.tsx.snap @@ -0,0 +1,9 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`LoginWithBiometricsSwitch should render correctly 1`] = ` + +`; diff --git a/app/components/UI/LoginOptionsSwitch/index.ts b/app/components/UI/LoginOptionsSwitch/index.ts new file mode 100644 index 00000000000..1de1c5d6af2 --- /dev/null +++ b/app/components/UI/LoginOptionsSwitch/index.ts @@ -0,0 +1,2 @@ +// eslint-disable-next-line import/prefer-default-export +export { default as LoginOptionsSwitch } from './LoginOptionsSwitch'; diff --git a/app/components/UI/LoginOptionsSwitch/styles.ts b/app/components/UI/LoginOptionsSwitch/styles.ts new file mode 100644 index 00000000000..a8c8c05fb3b --- /dev/null +++ b/app/components/UI/LoginOptionsSwitch/styles.ts @@ -0,0 +1,27 @@ +/* eslint-disable import/prefer-default-export */ +import { fontStyles } from '../../../styles/common'; +import { StyleSheet } from 'react-native'; + +export const createStyles = (colors: any) => + StyleSheet.create({ + screen: { + flex: 1, + backgroundColor: colors.background.default, + }, + container: { + position: 'relative', + marginTop: 20, + marginBottom: 30, + }, + label: { + flex: 1, + fontSize: 16, + color: colors.text.default, + ...fontStyles.normal, + }, + switch: { + position: 'absolute', + top: 0, + right: 0, + }, + }); diff --git a/app/components/Views/ChoosePassword/index.js b/app/components/Views/ChoosePassword/index.js index a401a953940..8193b61f765 100644 --- a/app/components/Views/ChoosePassword/index.js +++ b/app/components/Views/ChoosePassword/index.js @@ -1,7 +1,6 @@ import React, { PureComponent } from 'react'; import PropTypes from 'prop-types'; import { - Switch, ActivityIndicator, Alert, Text, @@ -12,7 +11,6 @@ import { Image, InteractionManager, } from 'react-native'; -// eslint-disable-next-line import/no-unresolved import CheckBox from '@react-native-community/checkbox'; import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view'; import AsyncStorage from '@react-native-community/async-storage'; @@ -27,7 +25,7 @@ import { setLockTime } from '../../../actions/settings'; import StyledButton from '../../UI/StyledButton'; import Engine from '../../../core/Engine'; import Device from '../../../util/device'; -import { fontStyles, colors as importedColors } from '../../../styles/common'; +import { fontStyles } from '../../../styles/common'; import { strings } from '../../../../locales/i18n'; import { getOnboardingNavbarOptions } from '../../UI/Navbar'; import SecureKeychain from '../../../core/SecureKeychain'; @@ -62,6 +60,7 @@ import { IOS_I_UNDERSTAND_BUTTON_ID, ANDROID_I_UNDERSTAND_BUTTON_ID, } from '../../../constants/test-ids'; +import { LoginOptionsSwitch } from '../../UI/LoginOptionsSwitch'; const createStyles = (colors) => StyleSheet.create({ @@ -566,51 +565,16 @@ class ChoosePassword extends PureComponent { }; renderSwitch = () => { - const { biometryType, rememberMe, biometryChoice } = this.state; - const colors = this.context.colors || mockTheme.colors; - const styles = createStyles(colors); - + const { biometryType } = this.state; + const handleUpdateRememberMe = (rememberMe) => { + this.setState({ rememberMe }); + }; return ( - - {biometryType ? ( - <> - - {strings(`biometrics.enable_${biometryType.toLowerCase()}`)} - - - - - - ) : ( - <> - - {strings(`choose_password.remember_me`)} - - this.setState({ rememberMe })} // eslint-disable-line react/jsx-no-bind - value={rememberMe} - style={styles.biometrySwitch} - trackColor={{ - true: colors.primary.default, - false: colors.border.muted, - }} - thumbColor={importedColors.white} - ios_backgroundColor={colors.border.muted} - testID={'remember-me-toggle'} - /> - - )} - + ); }; diff --git a/app/components/Views/ImportFromSeed/index.js b/app/components/Views/ImportFromSeed/index.js index aedd23ad63f..fda5f47508d 100644 --- a/app/components/Views/ImportFromSeed/index.js +++ b/app/components/Views/ImportFromSeed/index.js @@ -1,7 +1,6 @@ import React, { PureComponent } from 'react'; import PropTypes from 'prop-types'; import { - Switch, ActivityIndicator, Alert, TouchableOpacity, @@ -21,7 +20,7 @@ import { logIn, passwordSet, seedphraseBackedUp } from '../../../actions/user'; import { setLockTime } from '../../../actions/settings'; import StyledButton from '../../UI/StyledButton'; import Engine from '../../../core/Engine'; -import { fontStyles, colors as importedColors } from '../../../styles/common'; +import { fontStyles } from '../../../styles/common'; import { strings } from '../../../../locales/i18n'; import SecureKeychain from '../../../core/SecureKeychain'; import AppConstants from '../../../core/AppConstants'; @@ -62,6 +61,7 @@ import { IMPORT_PASSWORD_CONTAINER_ID, SECRET_RECOVERY_PHRASE_INPUT_BOX_ID, } from '../../../constants/test-ids'; +import { LoginOptionsSwitch } from '../../UI/LoginOptionsSwitch'; const MINIMUM_SUPPORTED_CLIPBOARD_VERSION = 9; @@ -455,50 +455,15 @@ class ImportFromSeed extends PureComponent { }; renderSwitch = () => { - const colors = this.context.colors || mockTheme.colors; - const styles = createStyles(colors); - - if (this.state.biometryType) { - return ( - - - {strings( - `biometrics.enable_${this.state.biometryType.toLowerCase()}`, - )} - - - - ); - } - + const handleUpdateRememberMe = (rememberMe) => { + this.setState({ rememberMe }); + }; return ( - - - {strings(`choose_password.remember_me`)} - - this.setState({ rememberMe })} // eslint-disable-line react/jsx-no-bind - value={this.state.rememberMe} - style={styles.biometrySwitch} - trackColor={{ - true: colors.primary.default, - false: colors.border.muted, - }} - thumbColor={importedColors.white} - ios_backgroundColor={colors.border.muted} - testID={'remember-me-toggle'} - /> - + ); }; diff --git a/app/components/Views/Login/index.js b/app/components/Views/Login/index.js index a984e71c893..f8256383c49 100644 --- a/app/components/Views/Login/index.js +++ b/app/components/Views/Login/index.js @@ -1,7 +1,6 @@ import React, { PureComponent } from 'react'; import PropTypes from 'prop-types'; import { - Switch, Alert, ActivityIndicator, Text, @@ -17,12 +16,17 @@ import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view import Button from 'react-native-button'; import Engine from '../../../core/Engine'; import StyledButton from '../../UI/StyledButton'; -import { fontStyles, colors as importedColors } from '../../../styles/common'; +import { fontStyles } from '../../../styles/common'; import { strings } from '../../../../locales/i18n'; import SecureKeychain from '../../../core/SecureKeychain'; import FadeOutOverlay from '../../UI/FadeOutOverlay'; import setOnboardingWizardStep from '../../../actions/wizard'; -import { logIn, logOut, checkedAuth } from '../../../actions/user'; +import { + logIn, + logOut, + checkedAuth, + setIsUsingRememberMe, +} from '../../../actions/user'; import { connect } from 'react-redux'; import Device from '../../../util/device'; import { OutlinedTextField } from 'react-native-material-textfield'; @@ -49,6 +53,7 @@ import { LOGIN_PASSWORD_ERROR, RESET_WALLET_ID, } from '../../../constants/test-ids'; +import { LoginOptionsSwitch } from '../../UI/LoginOptionsSwitch'; const deviceHeight = Device.getDeviceHeight(); const breakPoint = deviceHeight < 700; @@ -221,6 +226,11 @@ class Login extends PureComponent { * TEMPORARY state for animation control on Nav/App/index.js */ checkedAuth: PropTypes.func, + + /** + * Action to set if the user is using remember me for authentication + */ + setIsUsingRememberMe: PropTypes.func, }; state = { @@ -301,6 +311,7 @@ class Login extends PureComponent { const credentials = await SecureKeychain.getGenericPassword(); if (credentials) { this.setState({ rememberMe: true }); + this.props.setIsUsingRememberMe(true); // Restore vault with existing credentials const { KeyringController } = Engine.context; try { @@ -328,6 +339,7 @@ class Login extends PureComponent { this.props.navigation.replace('HomeNav'); } catch (error) { this.setState({ rememberMe: false }); + this.props.setIsUsingRememberMe(false); Logger.error(error, 'Failed to login using Remember Me'); } } @@ -450,52 +462,30 @@ class Login extends PureComponent { this.setState({ biometryChoice }); }; - renderSwitch = () => { - const colors = this.context.colors || mockTheme.colors; - const styles = createStyles(colors); - - if (this.state.biometryType && !this.state.biometryPreviouslyDisabled) { - return ( - - - {strings( - `biometrics.enable_${this.state.biometryType.toLowerCase()}`, - )} - - - this.updateBiometryChoice(biometryChoice) - } // eslint-disable-line react/jsx-no-bind - value={this.state.biometryChoice} - style={styles.biometrySwitch} - trackColor={{ - true: colors.primary.default, - false: colors.border.muted, - }} - thumbColor={importedColors.white} - ios_backgroundColor={colors.border.muted} - /> - - ); + updateBiometryChoice = async (biometryChoice) => { + if (!biometryChoice) { + await AsyncStorage.setItem(BIOMETRY_CHOICE_DISABLED, TRUE); + } else { + await AsyncStorage.removeItem(BIOMETRY_CHOICE_DISABLED); } + this.setState({ biometryChoice }); + }; + renderSwitch = () => { + const handleUpdateRememberMe = (rememberMe) => { + this.setState({ rememberMe }); + this.props.setIsUsingRememberMe(rememberMe); + }; + const shouldRenderBiometricLogin = + this.state.biometryType && !this.state.biometryPreviouslyDisabled + ? this.state.biometryType + : null; return ( - - - {strings(`choose_password.remember_me`)} - - this.setState({ rememberMe })} // eslint-disable-line react/jsx-no-bind - value={this.state.rememberMe} - style={styles.biometrySwitch} - trackColor={{ - true: colors.primary.default, - false: colors.border.muted, - }} - thumbColor={importedColors.white} - ios_backgroundColor={colors.border.muted} - /> - + ); }; @@ -638,6 +628,8 @@ const mapDispatchToProps = (dispatch) => ({ logIn: () => dispatch(logIn()), logOut: () => dispatch(logOut()), checkedAuth: () => dispatch(checkedAuth('login')), + setIsUsingRememberMe: (isUsingRememberMe) => + dispatch(setIsUsingRememberMe(isUsingRememberMe)), }); export default connect(mapStateToProps, mapDispatchToProps)(Login); diff --git a/app/components/Views/ResetPassword/index.js b/app/components/Views/ResetPassword/index.js index 35c58a1c7f6..eb20d4386bf 100644 --- a/app/components/Views/ResetPassword/index.js +++ b/app/components/Views/ResetPassword/index.js @@ -2,7 +2,6 @@ import React, { PureComponent } from 'react'; import PropTypes from 'prop-types'; import { KeyboardAvoidingView, - Switch, ActivityIndicator, Alert, Text, @@ -14,7 +13,6 @@ import { Image, InteractionManager, } from 'react-native'; -// eslint-disable-next-line import/no-unresolved import CheckBox from '@react-native-community/checkbox'; import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view'; import AsyncStorage from '@react-native-community/async-storage'; @@ -28,11 +26,7 @@ import { setLockTime } from '../../../actions/settings'; import StyledButton from '../../UI/StyledButton'; import Engine from '../../../core/Engine'; import Device from '../../../util/device'; -import { - fontStyles, - baseStyles, - colors as importedColors, -} from '../../../styles/common'; +import { fontStyles, baseStyles } from '../../../styles/common'; import { strings } from '../../../../locales/i18n'; import { getNavigationOptionsTitle } from '../../UI/Navbar'; import SecureKeychain from '../../../core/SecureKeychain'; @@ -62,6 +56,7 @@ import { ANDROID_I_UNDERSTAND_BUTTON_ID, CONFIRM_CHANGE_PASSWORD_INPUT_BOX_ID, } from '../../../constants/test-ids'; +import { LoginOptionsSwitch } from '../../UI/LoginOptionsSwitch'; const createStyles = (colors) => StyleSheet.create({ @@ -231,15 +226,12 @@ const createStyles = (colors) => top: 0, right: 0, }, - // eslint-disable-next-line react-native/no-unused-styles strength_weak: { color: colors.error.default, }, - // eslint-disable-next-line react-native/no-unused-styles strength_good: { color: colors.primary.default, }, - // eslint-disable-next-line react-native/no-unused-styles strength_strong: { color: colors.success.default, }, @@ -548,50 +540,16 @@ class ResetPassword extends PureComponent { }; renderSwitch = () => { - const { biometryType, rememberMe, biometryChoice } = this.state; - const colors = this.context.colors || mockTheme.colors; - const styles = createStyles(colors); - + const { biometryType } = this.state; + const handleUpdateRememberMe = (rememberMe) => { + this.setState({ rememberMe }); + }; return ( - - {biometryType ? ( - <> - - {strings(`biometrics.enable_${biometryType.toLowerCase()}`)} - - - - - - ) : ( - <> - - {strings(`choose_password.remember_me`)} - - this.setState({ rememberMe })} // eslint-disable-line react/jsx-no-bind - value={rememberMe} - style={styles.biometrySwitch} - trackColor={{ - true: colors.primary.default, - false: colors.border.muted, - }} - thumbColor={importedColors.white} - ios_backgroundColor={colors.border.muted} - /> - - )} - + ); }; diff --git a/app/components/Views/Settings/SecuritySettings/__snapshots__/index.test.tsx.snap b/app/components/Views/Settings/SecuritySettings/__snapshots__/index.test.tsx.snap index 71d26178f21..720f8f4c305 100644 --- a/app/components/Views/Settings/SecuritySettings/__snapshots__/index.test.tsx.snap +++ b/app/components/Views/Settings/SecuritySettings/__snapshots__/index.test.tsx.snap @@ -3,6 +3,7 @@ exports[`SecuritySettings should render correctly 1`] = ` void; + testId: string; +} + +/** + * View that renders the toggle for security options + * This component assumes that the parent will manage the state of the toggle. This is because most of the state is global. + */ +const SecurityOptionToggle = ({ + title, + description, + value, + testId, + onOptionUpdated, +}: SecurityOptionsToggleProps) => { + const { colors } = useAppThemeFromContext() || mockTheme; + const styles = createStyles(colors); + + const handleOnValueChange = useCallback( + (newValue: boolean) => { + onOptionUpdated(newValue); + }, + [onOptionUpdated], + ); + return ( + + {title} + {description ? {description} : null} + + handleOnValueChange(newValue)} + trackColor={{ + true: colors.primary.default, + false: colors.border.muted, + }} + thumbColor={importedColors.white} + style={styles.switch} + ios_backgroundColor={colors.border.muted} + /> + + + ); +}; + +export default React.memo(SecurityOptionToggle); diff --git a/app/components/Views/Settings/SecuritySettings/components/SecurityOptionToggle/index.ts b/app/components/Views/Settings/SecuritySettings/components/SecurityOptionToggle/index.ts new file mode 100644 index 00000000000..e9aee4a1f04 --- /dev/null +++ b/app/components/Views/Settings/SecuritySettings/components/SecurityOptionToggle/index.ts @@ -0,0 +1,2 @@ +// eslint-disable-next-line import/prefer-default-export +export { default as SecurityOptionToggle } from './SecurityOptionToggle'; diff --git a/app/components/Views/Settings/SecuritySettings/components/SecurityOptionToggle/styles.ts b/app/components/Views/Settings/SecuritySettings/components/SecurityOptionToggle/styles.ts new file mode 100644 index 00000000000..ad34ff8d58d --- /dev/null +++ b/app/components/Views/Settings/SecuritySettings/components/SecurityOptionToggle/styles.ts @@ -0,0 +1,32 @@ +/* eslint-disable import/prefer-default-export */ +import { fontStyles } from '../../../../../../styles/common'; +import { StyleSheet } from 'react-native'; + +export const createStyles = (colors: any) => + StyleSheet.create({ + title: { + ...fontStyles.normal, + color: colors.text.default, + fontSize: 20, + lineHeight: 20, + paddingTop: 4, + marginTop: -4, + }, + desc: { + ...fontStyles.normal, + color: colors.text.alternative, + fontSize: 14, + lineHeight: 20, + marginTop: 12, + }, + switchElement: { + marginTop: 18, + alignSelf: 'flex-start', + }, + setting: { + marginTop: 50, + }, + switch: { + alignSelf: 'flex-start', + }, + }); diff --git a/app/components/Views/Settings/SecuritySettings/components/index.ts b/app/components/Views/Settings/SecuritySettings/components/index.ts new file mode 100644 index 00000000000..9d554fa537f --- /dev/null +++ b/app/components/Views/Settings/SecuritySettings/components/index.ts @@ -0,0 +1,2 @@ +// eslint-disable-next-line import/prefer-default-export +export { SecurityOptionToggle } from './SecurityOptionToggle'; diff --git a/app/components/Views/Settings/SecuritySettings/index.js b/app/components/Views/Settings/SecuritySettings/index.js index adf6dc48626..179d37c6f01 100644 --- a/app/components/Views/Settings/SecuritySettings/index.js +++ b/app/components/Views/Settings/SecuritySettings/index.js @@ -27,6 +27,7 @@ import { setPrivacyMode, setThirdPartyApiMode, } from '../../../../actions/privacy'; +import { setAllowLoginWithRememberMe } from '../../../../actions/security'; import { fontStyles, colors as importedColors, @@ -65,6 +66,7 @@ import { import { LEARN_MORE_URL } from '../../../../constants/urls'; import DeleteMetaMetricsData from './Sections/DeleteMetaMetricsData'; import DeleteWalletData from './Sections/DeleteWalletData'; +import { SecurityOptionToggle } from './components'; const isIos = Device.isIos(); @@ -296,6 +298,14 @@ class Settings extends PureComponent { * Type of network */ type: PropTypes.string, + /** + * Indicates whether privacy mode is enabled + */ + allowLoginWithRememberMe: PropTypes.bool, + /** + * Called to toggle privacy mode + */ + setAllowLoginWithRememberMe: PropTypes.func, }; state = { @@ -542,6 +552,10 @@ class Settings extends PureComponent { this.props.setPrivacyMode(value); }; + toggleRememberMe = (value) => { + this.props.setAllowLoginWithRememberMe(value); + }; + toggleThirdPartyAPI = (value) => { this.props.setThirdPartyApiMode(value); }; @@ -820,6 +834,15 @@ class Settings extends PureComponent { ); }; + renderRememberMeOptionSection = () => ( + + ); + renderDevicePasscodeSection = () => { const { styles, colors } = this.getStyles(); return ( @@ -1192,6 +1215,7 @@ class Settings extends PureComponent { {this.renderPasswordSection()} {this.renderAutoLockSection()} {biometryType && this.renderBiometricOptionsSection()} + {this.renderRememberMeOptionSection()} {biometryType && !biometryChoice && this.renderDevicePasscodeSection()} @@ -1236,6 +1260,7 @@ const mapStateToProps = (state) => ({ passwordHasBeenSet: state.user.passwordSet, seedphraseBackedUp: state.user.seedphraseBackedUp, type: state.engine.backgroundState.NetworkController.provider.type, + allowLoginWithRememberMe: state.security.allowLoginWithRememberMe, }); const mapDispatchToProps = (dispatch) => ({ @@ -1245,6 +1270,8 @@ const mapDispatchToProps = (dispatch) => ({ setPrivacyMode: (enabled) => dispatch(setPrivacyMode(enabled)), setThirdPartyApiMode: (enabled) => dispatch(setThirdPartyApiMode(enabled)), passwordSet: () => dispatch(passwordSet()), + setAllowLoginWithRememberMe: (enabled) => + dispatch(setAllowLoginWithRememberMe(enabled)), }); export default connect(mapStateToProps, mapDispatchToProps)(Settings); diff --git a/app/components/Views/Settings/SecuritySettings/index.test.tsx b/app/components/Views/Settings/SecuritySettings/index.test.tsx index d80b1c21aee..2dbae2c63c6 100644 --- a/app/components/Views/Settings/SecuritySettings/index.test.tsx +++ b/app/components/Views/Settings/SecuritySettings/index.test.tsx @@ -27,6 +27,9 @@ const initialState = { }, }, }, + security: { + allowLoginWithRememberMe: true, + }, }; const store = mockStore(initialState); diff --git a/app/constants/test-ids.js b/app/constants/test-ids.js index 32f7683fddd..135097b772d 100644 --- a/app/constants/test-ids.js +++ b/app/constants/test-ids.js @@ -67,3 +67,20 @@ export const WHATS_NEW_MODAL_CLOSE_BUTTON_ID = 'whats-new-modal-close-button'; export const WHATS_NEW_MODAL_GOT_IT_BUTTON_ID = 'whats-new-modal-got-it-button'; export const INPUT_NETWORK_NAME = 'input-network-name'; + +// Component library test ids +export const FAVICON_AVATAR_IMAGE_ID = 'favicon-avatar-image'; +export const NETWORK_AVATAR_IMAGE_ID = 'network-avatar-image'; +export const CHECKBOX_ICON_ID = 'checkbox-icon'; +export const SELECTABLE_LIST_ITEM_OVERLAY_ID = 'selectable-list-item-overlay'; +export const CONFIRMATION_MODAL_NORMAL_BUTTON_ID = + 'confirmation-modal-normal-button'; +export const CONFIRMATION_MODAL_DANGER_BUTTON_ID = + 'confirmation-modal-danger-button'; +export const TOKEN_AVATAR_IMAGE_ID = 'token-avatar-image'; +export const STACKED_AVATARS_OVERFLOW_COUNTER = + 'stacked-avatar-overflow-counter'; + +// LoginOptionsSwitch +export const LOGIN_WITH_BIOMETRICS_SWITCH = 'login-with-biometrics-switch'; +export const LOGIN_WITH_REMEMBER_ME_SWITCH = 'login-with-remember-me-switch'; diff --git a/app/reducers/index.js b/app/reducers/index.js index 6c08bd65a46..fb99777e178 100644 --- a/app/reducers/index.js +++ b/app/reducers/index.js @@ -17,6 +17,7 @@ import collectiblesReducer from './collectibles'; import recentsReducer from './recents'; import navigationReducer from './navigation'; import networkOnboardReducer from './networkSelector'; +import securityReducer from './security'; import { combineReducers } from 'redux'; const rootReducer = combineReducers({ @@ -39,6 +40,7 @@ const rootReducer = combineReducers({ infuraAvailability: infuraAvailabilityReducer, navigation: navigationReducer, networkOnboarded: networkOnboardReducer, + security: securityReducer, }); export default rootReducer; diff --git a/app/reducers/security/index.ts b/app/reducers/security/index.ts new file mode 100644 index 00000000000..8384c4885dc --- /dev/null +++ b/app/reducers/security/index.ts @@ -0,0 +1,26 @@ +/* eslint-disable @typescript-eslint/default-param-last */ +import { ActionType, Action } from '../../actions/security'; +import { SecuritySettingsState } from '../../actions/security/state'; +import { store } from '../../store'; + +const { isUsingRememberMe } = store.getState(); + +const initialState: Readonly = { + allowLoginWithRememberMe: isUsingRememberMe, +}; + +const securityReducer = ( + state: SecuritySettingsState = initialState, + action: Action, +): SecuritySettingsState => { + switch (action.type) { + case ActionType.SET_ALLOW_LOGIN_WITH_REMEMBER_ME: + return { + allowLoginWithRememberMe: action.enabled, + }; + default: + return state; + } +}; + +export default securityReducer; diff --git a/app/reducers/user/index.js b/app/reducers/user/index.js index 774ac4debb0..1e0345d146b 100644 --- a/app/reducers/user/index.js +++ b/app/reducers/user/index.js @@ -13,6 +13,7 @@ const initialState = { isAuthChecked: false, initialScreen: '', appTheme: AppThemeKey.os, + isUsingRememberMe: false, }; const userReducer = (state = initialState, action) => { @@ -104,6 +105,11 @@ const userReducer = (state = initialState, action) => { ...state, appTheme: action.payload.theme, }; + case 'SET_IS_USING_REMEMBER_ME': + return { + ...state, + isUsingRememberMe: action.payload.isUsingRememberMe, + }; default: return state; } diff --git a/app/util/testSetup.js b/app/util/testSetup.js index 4b4da4b3942..df02fcd8e26 100644 --- a/app/util/testSetup.js +++ b/app/util/testSetup.js @@ -88,9 +88,24 @@ jest.mock('../core/Engine', () => ({ }, })); -jest.mock('react-native-keychain', () => ({ - getSupportedBiometryType: () => Promise.resolve('FaceId'), -})); +const keychainMock = { + SECURITY_LEVEL_ANY: 'MOCK_SECURITY_LEVEL_ANY', + SECURITY_LEVEL_SECURE_SOFTWARE: 'MOCK_SECURITY_LEVEL_SECURE_SOFTWARE', + SECURITY_LEVEL_SECURE_HARDWARE: 'MOCK_SECURITY_LEVEL_SECURE_HARDWARE', + setGenericPassword: jest.fn(), + getGenericPassword: jest.fn(), + resetGenericPassword: jest.fn(), + BIOMETRY_TYPE: { + TOUCH_ID: 'TouchID', + FACE_ID: 'FaceID', + FINGERPRINT: 'Fingerprint', + FACE: 'Face', + IRIS: 'Iris', + }, + getSupportedBiometryType: jest.fn().mockReturnValue('FaceID'), +}; + +jest.mock('react-native-keychain', () => keychainMock); jest.mock('react-native-share', () => 'RNShare'); jest.mock('react-native-branch', () => ({ BranchSubscriber: () => { diff --git a/ios/Podfile.lock b/ios/Podfile.lock index b9855a51b93..a4881dfa174 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -841,4 +841,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: 5759da19ce141e5f8aca3a4f56ac232baa34e957 -COCOAPODS: 1.11.3 +COCOAPODS: 1.11.2 diff --git a/locales/languages/en.json b/locales/languages/en.json index c5653996282..51748790b00 100644 --- a/locales/languages/en.json +++ b/locales/languages/en.json @@ -1204,6 +1204,10 @@ "enable_device_passcode_ios": "Unlock with device passcode?", "enable_device_passcode_android": "Unlock with device PIN?" }, + "remember_me": { + "enable_remember_me": "Allow \"Remember me\"", + "enable_remember_me_description": "Turn on at your own risk. When \"Remember me\" is on, it gives anyone access to your MetaMask if they can access your phone." + }, "authentication": { "auth_prompt_title": "Authentication required", "auth_prompt_desc": "Please authenticate in order to use MetaMask", From f8cccb7ba0e1708d2583cc511849982ee9a52539 Mon Sep 17 00:00:00 2001 From: owencraston Date: Wed, 6 Jul 2022 15:59:50 -0400 Subject: [PATCH 02/17] set default state to true if user was already using remember me --- app/actions/user/index.js | 7 --- .../Views/Login/checkIfUsingRememberMe.ts | 20 ++++++++ app/components/Views/Login/index.js | 20 +++----- .../Sections/RememberMeOptionSection.tsx | 49 +++++++++++++++++++ .../SecurityOptionToggle.tsx | 5 +- .../Views/Settings/SecuritySettings/index.js | 29 +---------- app/reducers/security/index.ts | 5 +- app/reducers/user/index.js | 6 --- 8 files changed, 83 insertions(+), 58 deletions(-) create mode 100644 app/components/Views/Login/checkIfUsingRememberMe.ts create mode 100644 app/components/Views/Settings/SecuritySettings/Sections/RememberMeOptionSection.tsx diff --git a/app/actions/user/index.js b/app/actions/user/index.js index 06fa45a5958..3919fb17355 100644 --- a/app/actions/user/index.js +++ b/app/actions/user/index.js @@ -104,10 +104,3 @@ export function checkedAuth(initialScreen) { }, }; } - -export function setIsUsingRememberMe(isUsingRememberMe) { - return { - type: 'SET_IS_USING_REMEMBER_ME', - payload: { isUsingRememberMe }, - }; -} diff --git a/app/components/Views/Login/checkIfUsingRememberMe.ts b/app/components/Views/Login/checkIfUsingRememberMe.ts new file mode 100644 index 00000000000..67ab731b554 --- /dev/null +++ b/app/components/Views/Login/checkIfUsingRememberMe.ts @@ -0,0 +1,20 @@ +/* eslint-disable import/prefer-default-export */ +import SecureKeychain from '../../../core/SecureKeychain'; +import Engine from '../../../core/Engine'; +/** + * Checks to see if the user has enabled Remember Me and logs + * into the application if it is enabled. + */ +export const checkIfRememberMeEnabled = async () => { + const credentials = await SecureKeychain.getGenericPassword(); + if (credentials) { + // Restore vault with existing credentials + const { KeyringController } = Engine.context as any; + try { + await KeyringController.submitPassword(credentials.password); + return true; + } catch (error) { + return false; + } + } else return false; +}; diff --git a/app/components/Views/Login/index.js b/app/components/Views/Login/index.js index f8256383c49..6b3300ff07f 100644 --- a/app/components/Views/Login/index.js +++ b/app/components/Views/Login/index.js @@ -21,12 +21,8 @@ import { strings } from '../../../../locales/i18n'; import SecureKeychain from '../../../core/SecureKeychain'; import FadeOutOverlay from '../../UI/FadeOutOverlay'; import setOnboardingWizardStep from '../../../actions/wizard'; -import { - logIn, - logOut, - checkedAuth, - setIsUsingRememberMe, -} from '../../../actions/user'; +import { logIn, logOut, checkedAuth } from '../../../actions/user'; +import { setAllowLoginWithRememberMe } from '../../../actions/security'; import { connect } from 'react-redux'; import Device from '../../../util/device'; import { OutlinedTextField } from 'react-native-material-textfield'; @@ -228,9 +224,9 @@ class Login extends PureComponent { checkedAuth: PropTypes.func, /** - * Action to set if the user is using remember me for authentication + * Action to set if the user is using remember me */ - setIsUsingRememberMe: PropTypes.func, + setAllowLoginWithRememberMe: PropTypes.func, }; state = { @@ -311,7 +307,7 @@ class Login extends PureComponent { const credentials = await SecureKeychain.getGenericPassword(); if (credentials) { this.setState({ rememberMe: true }); - this.props.setIsUsingRememberMe(true); + this.props.setAllowLoginWithRememberMe(true); // Restore vault with existing credentials const { KeyringController } = Engine.context; try { @@ -339,7 +335,6 @@ class Login extends PureComponent { this.props.navigation.replace('HomeNav'); } catch (error) { this.setState({ rememberMe: false }); - this.props.setIsUsingRememberMe(false); Logger.error(error, 'Failed to login using Remember Me'); } } @@ -474,7 +469,6 @@ class Login extends PureComponent { renderSwitch = () => { const handleUpdateRememberMe = (rememberMe) => { this.setState({ rememberMe }); - this.props.setIsUsingRememberMe(rememberMe); }; const shouldRenderBiometricLogin = this.state.biometryType && !this.state.biometryPreviouslyDisabled @@ -628,8 +622,8 @@ const mapDispatchToProps = (dispatch) => ({ logIn: () => dispatch(logIn()), logOut: () => dispatch(logOut()), checkedAuth: () => dispatch(checkedAuth('login')), - setIsUsingRememberMe: (isUsingRememberMe) => - dispatch(setIsUsingRememberMe(isUsingRememberMe)), + setAllowLoginWithRememberMe: (enabled) => + dispatch(setAllowLoginWithRememberMe(enabled)), }); export default connect(mapStateToProps, mapDispatchToProps)(Login); diff --git a/app/components/Views/Settings/SecuritySettings/Sections/RememberMeOptionSection.tsx b/app/components/Views/Settings/SecuritySettings/Sections/RememberMeOptionSection.tsx new file mode 100644 index 00000000000..a2a1eb68f82 --- /dev/null +++ b/app/components/Views/Settings/SecuritySettings/Sections/RememberMeOptionSection.tsx @@ -0,0 +1,49 @@ +import React, { useState, useEffect, useCallback } from 'react'; +import { Alert } from 'react-native'; +import { SecurityOptionToggle } from '../components'; +import { strings } from '../../../../../../locales/i18n'; +import { checkIfRememberMeEnabled } from '../../../Login/checkIfUsingRememberMe'; +import { useSelector, useDispatch } from 'react-redux'; +import { setAllowLoginWithRememberMe } from '../../../../../actions/security'; + +const RememberMeOptionSection = () => { + const allowLoginWithRememberMe = useSelector( + (state: any) => state.security.allowLoginWithRememberMe, + ); + const [isUsingRememberMe, setIsUsingRememberMe] = useState(false); + useEffect(() => { + const checkIfAlreadyUsingRememberMe = async () => { + const isUsingRememberMeResult = await checkIfRememberMeEnabled(); + setIsUsingRememberMe(isUsingRememberMeResult); + }; + checkIfAlreadyUsingRememberMe(); + }, []); + + const dispatch = useDispatch(); + + const toggleRememberMe = useCallback( + (value: boolean) => { + dispatch(setAllowLoginWithRememberMe(value)); + }, + [dispatch], + ); + + const onValueChanged = useCallback( + (enabled: boolean) => { + isUsingRememberMe ? Alert.alert('no bro') : toggleRememberMe(enabled); + }, + [isUsingRememberMe, toggleRememberMe], + ); + + return ( + onValueChanged(value)} + disabled={isUsingRememberMe} + /> + ); +}; + +export default React.memo(RememberMeOptionSection); diff --git a/app/components/Views/Settings/SecuritySettings/components/SecurityOptionToggle/SecurityOptionToggle.tsx b/app/components/Views/Settings/SecuritySettings/components/SecurityOptionToggle/SecurityOptionToggle.tsx index 02a5022bd40..461a5d87888 100644 --- a/app/components/Views/Settings/SecuritySettings/components/SecurityOptionToggle/SecurityOptionToggle.tsx +++ b/app/components/Views/Settings/SecuritySettings/components/SecurityOptionToggle/SecurityOptionToggle.tsx @@ -12,7 +12,8 @@ interface SecurityOptionsToggleProps { description?: string; value: boolean; onOptionUpdated: (enabled: boolean) => void; - testId: string; + testId?: string; + disabled?: boolean; } /** @@ -25,6 +26,7 @@ const SecurityOptionToggle = ({ value, testId, onOptionUpdated, + disabled, }: SecurityOptionsToggleProps) => { const { colors } = useAppThemeFromContext() || mockTheme; const styles = createStyles(colors); @@ -50,6 +52,7 @@ const SecurityOptionToggle = ({ thumbColor={importedColors.white} style={styles.switch} ios_backgroundColor={colors.border.muted} + disabled={disabled} /> diff --git a/app/components/Views/Settings/SecuritySettings/index.js b/app/components/Views/Settings/SecuritySettings/index.js index 179d37c6f01..01fc3879057 100644 --- a/app/components/Views/Settings/SecuritySettings/index.js +++ b/app/components/Views/Settings/SecuritySettings/index.js @@ -27,7 +27,6 @@ import { setPrivacyMode, setThirdPartyApiMode, } from '../../../../actions/privacy'; -import { setAllowLoginWithRememberMe } from '../../../../actions/security'; import { fontStyles, colors as importedColors, @@ -66,7 +65,7 @@ import { import { LEARN_MORE_URL } from '../../../../constants/urls'; import DeleteMetaMetricsData from './Sections/DeleteMetaMetricsData'; import DeleteWalletData from './Sections/DeleteWalletData'; -import { SecurityOptionToggle } from './components'; +import RememberMeOptionSection from './Sections/RememberMeOptionSection'; const isIos = Device.isIos(); @@ -298,14 +297,6 @@ class Settings extends PureComponent { * Type of network */ type: PropTypes.string, - /** - * Indicates whether privacy mode is enabled - */ - allowLoginWithRememberMe: PropTypes.bool, - /** - * Called to toggle privacy mode - */ - setAllowLoginWithRememberMe: PropTypes.func, }; state = { @@ -552,10 +543,6 @@ class Settings extends PureComponent { this.props.setPrivacyMode(value); }; - toggleRememberMe = (value) => { - this.props.setAllowLoginWithRememberMe(value); - }; - toggleThirdPartyAPI = (value) => { this.props.setThirdPartyApiMode(value); }; @@ -834,15 +821,6 @@ class Settings extends PureComponent { ); }; - renderRememberMeOptionSection = () => ( - - ); - renderDevicePasscodeSection = () => { const { styles, colors } = this.getStyles(); return ( @@ -1215,7 +1193,7 @@ class Settings extends PureComponent { {this.renderPasswordSection()} {this.renderAutoLockSection()} {biometryType && this.renderBiometricOptionsSection()} - {this.renderRememberMeOptionSection()} + {biometryType && !biometryChoice && this.renderDevicePasscodeSection()} @@ -1260,7 +1238,6 @@ const mapStateToProps = (state) => ({ passwordHasBeenSet: state.user.passwordSet, seedphraseBackedUp: state.user.seedphraseBackedUp, type: state.engine.backgroundState.NetworkController.provider.type, - allowLoginWithRememberMe: state.security.allowLoginWithRememberMe, }); const mapDispatchToProps = (dispatch) => ({ @@ -1270,8 +1247,6 @@ const mapDispatchToProps = (dispatch) => ({ setPrivacyMode: (enabled) => dispatch(setPrivacyMode(enabled)), setThirdPartyApiMode: (enabled) => dispatch(setThirdPartyApiMode(enabled)), passwordSet: () => dispatch(passwordSet()), - setAllowLoginWithRememberMe: (enabled) => - dispatch(setAllowLoginWithRememberMe(enabled)), }); export default connect(mapStateToProps, mapDispatchToProps)(Settings); diff --git a/app/reducers/security/index.ts b/app/reducers/security/index.ts index 8384c4885dc..7119be56407 100644 --- a/app/reducers/security/index.ts +++ b/app/reducers/security/index.ts @@ -1,12 +1,9 @@ /* eslint-disable @typescript-eslint/default-param-last */ import { ActionType, Action } from '../../actions/security'; import { SecuritySettingsState } from '../../actions/security/state'; -import { store } from '../../store'; - -const { isUsingRememberMe } = store.getState(); const initialState: Readonly = { - allowLoginWithRememberMe: isUsingRememberMe, + allowLoginWithRememberMe: false, }; const securityReducer = ( diff --git a/app/reducers/user/index.js b/app/reducers/user/index.js index 1e0345d146b..774ac4debb0 100644 --- a/app/reducers/user/index.js +++ b/app/reducers/user/index.js @@ -13,7 +13,6 @@ const initialState = { isAuthChecked: false, initialScreen: '', appTheme: AppThemeKey.os, - isUsingRememberMe: false, }; const userReducer = (state = initialState, action) => { @@ -105,11 +104,6 @@ const userReducer = (state = initialState, action) => { ...state, appTheme: action.payload.theme, }; - case 'SET_IS_USING_REMEMBER_ME': - return { - ...state, - isUsingRememberMe: action.payload.isUsingRememberMe, - }; default: return state; } From eba3b6013e658d0604c62417981397ae56219ced Mon Sep 17 00:00:00 2001 From: owencraston Date: Wed, 6 Jul 2022 19:25:59 -0400 Subject: [PATCH 03/17] make user validate password before disabling remember me --- android/.project | 11 -- .../org.eclipse.buildship.core.prefs | 11 -- app/components/Nav/App/index.js | 5 + .../LoginOptionsSwitch.test.tsx | 1 + .../LoginOptionsSwitch/LoginOptionsSwitch.tsx | 11 +- .../LoginOptionsSwitch.test.tsx.snap | 1 + .../SecurityOptionToggle.tsx | 7 +- .../SecurityOptionToggle/index.ts | 0 .../SecurityOptionToggle/styles.ts | 2 +- .../TurnOffRememberMeModal.tsx | 123 ++++++++++++++++++ .../UI/TurnOffRememberMeModal/index.ts | 2 + .../UI/TurnOffRememberMeModal/styles.ts | 28 ++++ app/components/Views/ChoosePassword/index.js | 3 +- app/components/Views/ImportFromSeed/index.js | 5 +- .../Views/Login/checkIfUsingRememberMe.ts | 20 --- app/components/Views/Login/index.js | 1 + app/components/Views/ResetPassword/index.js | 3 +- .../Sections/RememberMeOptionSection.tsx | 18 ++- .../__snapshots__/index.test.tsx.snap | 2 - .../SecuritySettings/components/index.ts | 2 - app/constants/navigation/Routes.ts | 1 + app/constants/test-ids.js | 1 + .../authentication/checkIfUsingRememberMe.ts | 45 +++++++ app/util/authentication/index.ts | 2 + app/util/password/index.js | 18 --- app/util/password/index.ts | 69 ++++++++++ bitrise.yml | 11 ++ ios/MetaMask.xcodeproj/project.pbxproj | 12 ++ locales/languages/en.json | 4 - package.json | 3 + yarn.lock | 13 ++ 31 files changed, 343 insertions(+), 92 deletions(-) rename app/components/{Views/Settings/SecuritySettings/components => UI}/SecurityOptionToggle/SecurityOptionToggle.tsx (90%) rename app/components/{Views/Settings/SecuritySettings/components => UI}/SecurityOptionToggle/index.ts (100%) rename app/components/{Views/Settings/SecuritySettings/components => UI}/SecurityOptionToggle/styles.ts (91%) create mode 100644 app/components/UI/TurnOffRememberMeModal/TurnOffRememberMeModal.tsx create mode 100644 app/components/UI/TurnOffRememberMeModal/index.ts create mode 100644 app/components/UI/TurnOffRememberMeModal/styles.ts delete mode 100644 app/components/Views/Login/checkIfUsingRememberMe.ts delete mode 100644 app/components/Views/Settings/SecuritySettings/components/index.ts create mode 100644 app/util/authentication/checkIfUsingRememberMe.ts create mode 100644 app/util/authentication/index.ts delete mode 100644 app/util/password/index.js create mode 100644 app/util/password/index.ts diff --git a/android/.project b/android/.project index 649ee92486f..3cf8618bf4c 100644 --- a/android/.project +++ b/android/.project @@ -14,15 +14,4 @@ org.eclipse.buildship.core.gradleprojectnature - - - 1659034298708 - - 30 - - org.eclipse.core.resources.regexFilterMatcher - node_modules|.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ - - - diff --git a/android/.settings/org.eclipse.buildship.core.prefs b/android/.settings/org.eclipse.buildship.core.prefs index 61544433b64..e8895216fd3 100644 --- a/android/.settings/org.eclipse.buildship.core.prefs +++ b/android/.settings/org.eclipse.buildship.core.prefs @@ -1,13 +1,2 @@ -arguments= -auto.sync=false -build.scans.enabled=false -connection.gradle.distribution=GRADLE_DISTRIBUTION(WRAPPER) connection.project.dir= eclipse.preferences.version=1 -gradle.user.home= -java.home=/Library/Java/JavaVirtualMachines/zulu-11.jdk/Contents/Home -jvm.arguments= -offline.mode=false -override.workspace.settings=true -show.console.view=true -show.executions.view=true diff --git a/app/components/Nav/App/index.js b/app/components/Nav/App/index.js index 238353df91d..8746a67fe83 100644 --- a/app/components/Nav/App/index.js +++ b/app/components/Nav/App/index.js @@ -54,6 +54,7 @@ import ModalConfirmation from '../../../component-library/components/Modals/Moda import Toast, { ToastContext, } from '../../../component-library/components/Toast'; +import { TurnOffRememberMeModal } from '../../../components/UI/TurnOffRememberMeModal'; const Stack = createStackNavigator(); /** @@ -351,6 +352,10 @@ const App = ({ userLoggedIn }) => { component={ModalConfirmation} /> + ); diff --git a/app/components/UI/LoginOptionsSwitch/LoginOptionsSwitch.test.tsx b/app/components/UI/LoginOptionsSwitch/LoginOptionsSwitch.test.tsx index c4629b087ef..e9f301c780d 100644 --- a/app/components/UI/LoginOptionsSwitch/LoginOptionsSwitch.test.tsx +++ b/app/components/UI/LoginOptionsSwitch/LoginOptionsSwitch.test.tsx @@ -14,6 +14,7 @@ describe('LoginWithBiometricsSwitch', () => { diff --git a/app/components/UI/LoginOptionsSwitch/LoginOptionsSwitch.tsx b/app/components/UI/LoginOptionsSwitch/LoginOptionsSwitch.tsx index ee54594836c..4e9c1ace4ad 100644 --- a/app/components/UI/LoginOptionsSwitch/LoginOptionsSwitch.tsx +++ b/app/components/UI/LoginOptionsSwitch/LoginOptionsSwitch.tsx @@ -12,6 +12,7 @@ import { useSelector } from 'react-redux'; interface Props { shouldRenderBiometricOption: BIOMETRY_TYPE | null; + initialBiometryChoice: boolean; onUpdateBiometryChoice: (biometryEnabled: boolean) => void; onUpdateRememberMe: (rememberMeEnabled: boolean) => void; } @@ -24,6 +25,7 @@ interface Props { */ const LoginOptionsSwitch = ({ shouldRenderBiometricOption, + initialBiometryChoice, onUpdateBiometryChoice, onUpdateRememberMe, }: Props) => { @@ -32,7 +34,9 @@ const LoginOptionsSwitch = ({ const allowLoginWithRememberMe = useSelector( (state: any) => state.security.allowLoginWithRememberMe, ); - const [biometryEnabled, setBiometryEnabled] = useState(false); + const [biometryEnabled, setBiometryEnabled] = useState( + initialBiometryChoice, + ); const [rememberMeEnabled, setRememberMeEnabled] = useState(false); const onBiometryValueChanged = useCallback(async () => { @@ -68,10 +72,7 @@ const LoginOptionsSwitch = ({ /> ); - } else if ( - shouldRenderBiometricOption === null && - allowLoginWithRememberMe === true - ) { + } else if (shouldRenderBiometricOption === null && allowLoginWithRememberMe) { return ( diff --git a/app/components/UI/LoginOptionsSwitch/__snapshots__/LoginOptionsSwitch.test.tsx.snap b/app/components/UI/LoginOptionsSwitch/__snapshots__/LoginOptionsSwitch.test.tsx.snap index a274ea0fa67..048a5d63604 100644 --- a/app/components/UI/LoginOptionsSwitch/__snapshots__/LoginOptionsSwitch.test.tsx.snap +++ b/app/components/UI/LoginOptionsSwitch/__snapshots__/LoginOptionsSwitch.test.tsx.snap @@ -2,6 +2,7 @@ exports[`LoginWithBiometricsSwitch should render correctly 1`] = ` diff --git a/app/components/UI/TurnOffRememberMeModal/TurnOffRememberMeModal.tsx b/app/components/UI/TurnOffRememberMeModal/TurnOffRememberMeModal.tsx new file mode 100644 index 00000000000..53b49b9371e --- /dev/null +++ b/app/components/UI/TurnOffRememberMeModal/TurnOffRememberMeModal.tsx @@ -0,0 +1,123 @@ +import React, { useState, useRef, useCallback } from 'react'; +import { View, TouchableWithoutFeedback, Keyboard } from 'react-native'; +import BaseText, { + BaseTextVariant, +} from '../../../component-library/components/BaseText'; +import { OutlinedTextField } from 'react-native-material-textfield'; +import { createStyles } from './styles'; +import ReusableModal, { ReusableModalRef } from '../ReusableModal'; +import WarningExistingUserModal from '../WarningExistingUserModal'; +import { strings } from '../../../../locales/i18n'; +import { useTheme } from '../../../util/theme'; +import Routes from '../../../constants/navigation/Routes'; +import { createNavigationDetails } from '../../..//util/navigation/navUtils'; +import { doesPasswordMatch } from '../../../util/password'; +import Engine from '../../../core/Engine'; +import { logOut } from '../../../actions/user'; +import { setAllowLoginWithRememberMe } from '../../../actions/security'; +import { useDispatch } from 'react-redux'; +import SecureKeychain from '../../../core/SecureKeychain'; +import debounce from 'lodash/debounce'; +import { TURN_OFF_REMEMBER_ME_MODAL } from '../../../constants/test-ids'; + +export const createTurnOffRememberMeModalNavDetails = createNavigationDetails( + Routes.MODAL.ROOT_MODAL_FLOW, + Routes.MODAL.TURN_OFF_REMEMBER_ME, +); + +const TurnOffRememberMeModal = () => { + const { colors, themeAppearance } = useTheme(); + const styles = createStyles(colors); + const dispatch = useDispatch(); + + const modalRef = useRef(null); + + const [passwordText, setPasswordText] = useState(''); + const [disableButton, setDisableButton] = useState(true); + + const isValidPassword = useCallback( + async (text: string): Promise => { + const response = await doesPasswordMatch(text); + return response.valid; + }, + [], + ); + + const debouncedIsValidPassword = useCallback( + async (text) => + debounce(setDisableButton(!(await isValidPassword(text))), 200), + [isValidPassword], + ); + + const checkPassword = useCallback( + async (text: string) => { + setPasswordText(text); + debouncedIsValidPassword(text); + }, + [debouncedIsValidPassword], + ); + + const dismissModal = (cb?: () => void): void => + modalRef?.current?.dismissModal(cb); + + const triggerClose = () => dismissModal(); + + const turnOffRememberMeAndLockApp = useCallback(async () => { + const { KeyringController } = Engine.context as any; + await SecureKeychain.resetGenericPassword(); + await KeyringController.setLocked(); + dispatch(setAllowLoginWithRememberMe(false)); + dispatch(logOut()); + }, [dispatch]); + + const disableRememberMe = useCallback(async () => { + dismissModal(async () => await turnOffRememberMeAndLockApp()); + }, [turnOffRememberMeAndLockApp]); + + return ( + + + + + + {strings('turn_off_remember_me.title')} + + + {strings('turn_off_remember_me.description')} + + + + + + + ); +}; + +export default React.memo(TurnOffRememberMeModal); diff --git a/app/components/UI/TurnOffRememberMeModal/index.ts b/app/components/UI/TurnOffRememberMeModal/index.ts new file mode 100644 index 00000000000..0ce7d6e4a77 --- /dev/null +++ b/app/components/UI/TurnOffRememberMeModal/index.ts @@ -0,0 +1,2 @@ +/* eslint-disable import/prefer-default-export */ +export { default as TurnOffRememberMeModal } from './TurnOffRememberMeModal'; diff --git a/app/components/UI/TurnOffRememberMeModal/styles.ts b/app/components/UI/TurnOffRememberMeModal/styles.ts new file mode 100644 index 00000000000..35a9dd887d2 --- /dev/null +++ b/app/components/UI/TurnOffRememberMeModal/styles.ts @@ -0,0 +1,28 @@ +/* eslint-disable import/prefer-default-export */ +import { fontStyles } from '../../../styles/common'; +import { StyleSheet } from 'react-native'; +import Device from '../../../util/device'; + +const breakPoint = Device.getDeviceHeight() < 700; + +export const createStyles = (colors: any) => + StyleSheet.create({ + areYouSure: { + width: '100%', + padding: breakPoint ? 16 : 24, + justifyContent: 'center', + alignSelf: 'center', + }, + textStyle: { + paddingVertical: 12, + textAlign: 'center', + }, + bold: { + ...fontStyles.bold, + }, + input: { + ...fontStyles.normal, + fontSize: 16, + color: colors.text.default, + }, + }); diff --git a/app/components/Views/ChoosePassword/index.js b/app/components/Views/ChoosePassword/index.js index 8193b61f765..6763a83327e 100644 --- a/app/components/Views/ChoosePassword/index.js +++ b/app/components/Views/ChoosePassword/index.js @@ -565,13 +565,14 @@ class ChoosePassword extends PureComponent { }; renderSwitch = () => { - const { biometryType } = this.state; + const { biometryType, biometryChoice } = this.state; const handleUpdateRememberMe = (rememberMe) => { this.setState({ rememberMe }); }; return ( diff --git a/app/components/Views/ImportFromSeed/index.js b/app/components/Views/ImportFromSeed/index.js index fda5f47508d..739e0bbc8bc 100644 --- a/app/components/Views/ImportFromSeed/index.js +++ b/app/components/Views/ImportFromSeed/index.js @@ -394,10 +394,6 @@ class ImportFromSeed extends PureComponent { } }; - onBiometryChoiceChange = (value) => { - this.setState({ biometryChoice: value }); - }; - clearSecretRecoveryPhrase = async (seed) => { // get clipboard contents const clipboardContents = await Clipboard.getString(); @@ -461,6 +457,7 @@ class ImportFromSeed extends PureComponent { return ( diff --git a/app/components/Views/Login/checkIfUsingRememberMe.ts b/app/components/Views/Login/checkIfUsingRememberMe.ts deleted file mode 100644 index 67ab731b554..00000000000 --- a/app/components/Views/Login/checkIfUsingRememberMe.ts +++ /dev/null @@ -1,20 +0,0 @@ -/* eslint-disable import/prefer-default-export */ -import SecureKeychain from '../../../core/SecureKeychain'; -import Engine from '../../../core/Engine'; -/** - * Checks to see if the user has enabled Remember Me and logs - * into the application if it is enabled. - */ -export const checkIfRememberMeEnabled = async () => { - const credentials = await SecureKeychain.getGenericPassword(); - if (credentials) { - // Restore vault with existing credentials - const { KeyringController } = Engine.context as any; - try { - await KeyringController.submitPassword(credentials.password); - return true; - } catch (error) { - return false; - } - } else return false; -}; diff --git a/app/components/Views/Login/index.js b/app/components/Views/Login/index.js index 6b3300ff07f..a7273d99204 100644 --- a/app/components/Views/Login/index.js +++ b/app/components/Views/Login/index.js @@ -477,6 +477,7 @@ class Login extends PureComponent { return ( diff --git a/app/components/Views/ResetPassword/index.js b/app/components/Views/ResetPassword/index.js index eb20d4386bf..c0de48a8941 100644 --- a/app/components/Views/ResetPassword/index.js +++ b/app/components/Views/ResetPassword/index.js @@ -540,13 +540,14 @@ class ResetPassword extends PureComponent { }; renderSwitch = () => { - const { biometryType } = this.state; + const { biometryType, biometryChoice } = this.state; const handleUpdateRememberMe = (rememberMe) => { this.setState({ rememberMe }); }; return ( diff --git a/app/components/Views/Settings/SecuritySettings/Sections/RememberMeOptionSection.tsx b/app/components/Views/Settings/SecuritySettings/Sections/RememberMeOptionSection.tsx index a2a1eb68f82..d6b78398027 100644 --- a/app/components/Views/Settings/SecuritySettings/Sections/RememberMeOptionSection.tsx +++ b/app/components/Views/Settings/SecuritySettings/Sections/RememberMeOptionSection.tsx @@ -1,19 +1,22 @@ import React, { useState, useEffect, useCallback } from 'react'; -import { Alert } from 'react-native'; -import { SecurityOptionToggle } from '../components'; +import { SecurityOptionToggle } from '../../../../UI/SecurityOptionToggle'; import { strings } from '../../../../../../locales/i18n'; -import { checkIfRememberMeEnabled } from '../../../Login/checkIfUsingRememberMe'; +import { checkIfUsingRememberMe } from '../../../../../util/authentication'; import { useSelector, useDispatch } from 'react-redux'; import { setAllowLoginWithRememberMe } from '../../../../../actions/security'; +import { useNavigation } from '@react-navigation/native'; +import { createTurnOffRememberMeModalNavDetails } from '../../../..//UI/TurnOffRememberMeModal/TurnOffRememberMeModal'; const RememberMeOptionSection = () => { + const { navigate } = useNavigation(); const allowLoginWithRememberMe = useSelector( (state: any) => state.security.allowLoginWithRememberMe, ); + const [isUsingRememberMe, setIsUsingRememberMe] = useState(false); useEffect(() => { const checkIfAlreadyUsingRememberMe = async () => { - const isUsingRememberMeResult = await checkIfRememberMeEnabled(); + const isUsingRememberMeResult = await checkIfUsingRememberMe(); setIsUsingRememberMe(isUsingRememberMeResult); }; checkIfAlreadyUsingRememberMe(); @@ -30,9 +33,11 @@ const RememberMeOptionSection = () => { const onValueChanged = useCallback( (enabled: boolean) => { - isUsingRememberMe ? Alert.alert('no bro') : toggleRememberMe(enabled); + isUsingRememberMe + ? navigate(...createTurnOffRememberMeModalNavDetails()) + : toggleRememberMe(enabled); }, - [isUsingRememberMe, toggleRememberMe], + [isUsingRememberMe, navigate, toggleRememberMe], ); return ( @@ -41,7 +46,6 @@ const RememberMeOptionSection = () => { description={strings(`remember_me.enable_remember_me_description`)} value={allowLoginWithRememberMe} onOptionUpdated={(value) => onValueChanged(value)} - disabled={isUsingRememberMe} /> ); }; diff --git a/app/components/Views/Settings/SecuritySettings/__snapshots__/index.test.tsx.snap b/app/components/Views/Settings/SecuritySettings/__snapshots__/index.test.tsx.snap index 720f8f4c305..71d26178f21 100644 --- a/app/components/Views/Settings/SecuritySettings/__snapshots__/index.test.tsx.snap +++ b/app/components/Views/Settings/SecuritySettings/__snapshots__/index.test.tsx.snap @@ -3,7 +3,6 @@ exports[`SecuritySettings should render correctly 1`] = ` => { + const biometryChoice = await AsyncStorage.getItem(BIOMETRY_CHOICE); + // since we do not allow remember me to be used with biometrics we can eagerly return false + if (biometryChoice) { + return false; + } + // since we do not allow remember me to be used with passcode we can eagerly return false + const passcodeChoice = await AsyncStorage.getItem(PASSCODE_CHOICE); + if (passcodeChoice !== '' && passcodeChoice === TRUE) { + return false; + } + const credentials = await SecureKeychain.getGenericPassword(); + if (credentials) { + // Restore vault with existing credentials + const { KeyringController } = Engine.context as any; + try { + // this is being used a hack to verify that the credentials are valid + await KeyringController.exportSeedPhrase(credentials.password); + return true; + } catch (error) { + Logger.log( + 'Error in checkIfUsingRememberMe while calling KeyringController.exportSeedPhrase', + error, + ); + return false; + } + } else return false; +}; + +export default checkIfUsingRememberMe; diff --git a/app/util/authentication/index.ts b/app/util/authentication/index.ts new file mode 100644 index 00000000000..e47ba7dcb66 --- /dev/null +++ b/app/util/authentication/index.ts @@ -0,0 +1,2 @@ +// eslint-disable-next-line import/prefer-default-export +export { default as checkIfUsingRememberMe } from './checkIfUsingRememberMe'; diff --git a/app/util/password/index.js b/app/util/password/index.js deleted file mode 100644 index e630130c355..00000000000 --- a/app/util/password/index.js +++ /dev/null @@ -1,18 +0,0 @@ -export const MIN_PASSWORD_LENGTH = 8; -export const getPasswordStrengthWord = (strength) => { - switch (strength) { - case 0: - return 'weak'; - case 1: - return 'weak'; - case 2: - return 'weak'; - case 3: - return 'good'; - case 4: - return 'strong'; - } -}; - -export const passwordRequirementsMet = (password) => - password.length >= MIN_PASSWORD_LENGTH; diff --git a/app/util/password/index.ts b/app/util/password/index.ts new file mode 100644 index 00000000000..91cfe71b28c --- /dev/null +++ b/app/util/password/index.ts @@ -0,0 +1,69 @@ +import SecureKeychain from '../../core/SecureKeychain'; +import Engine from '../../core/Engine'; + +export const MIN_PASSWORD_LENGTH = 8; +type PasswordStrength = 0 | 1 | 2 | 3 | 4; + +export const getPasswordStrengthWord = (strength: PasswordStrength) => { + switch (strength) { + case 0: + return 'weak'; + case 1: + return 'weak'; + case 2: + return 'weak'; + case 3: + return 'good'; + case 4: + return 'strong'; + } +}; + +export const passwordRequirementsMet = (password: string) => + password.length >= MIN_PASSWORD_LENGTH; + +interface PasswordValidationResponse { + valid: boolean; + message: string; +} + +export const doesPasswordMatch = async ( + input: string, +): Promise => { + try { + // first try to get the stored password + const credentials = await SecureKeychain.getGenericPassword(); + if (credentials) { + try { + // then we verify if the stored password matches the one that can decrypt the vault + const { KeyringController } = Engine.context as any; + await KeyringController.exportSeedPhrase(credentials.password); + // now that we are confident that the user is logged in, we can test that the input matches + if (input === credentials.password) { + return { + valid: true, + message: 'The input matches the stored password', + }; + } + return { + valid: false, + message: 'The input does not match the stored password', + }; + } catch (error: any) { + return { + valid: false, + message: error.toString(), + }; + } + } + return { + valid: false, + message: 'no password stored', + }; + } catch (error: any) { + return { + valid: false, + message: error.toString(), + }; + } +}; diff --git a/bitrise.yml b/bitrise.yml index 9ca1343e01b..4b6ac910461 100644 --- a/bitrise.yml +++ b/bitrise.yml @@ -323,10 +323,21 @@ app: PROJECT_LOCATION_IOS: ios - opts: is_expand: false +<<<<<<< HEAD VERSION_NAME: 5.5.0 - opts: is_expand: false VERSION_NUMBER: 939 +======= + VERSION_NAME: 5.4.2 + - opts: + is_expand: false +<<<<<<< HEAD + VERSION_NUMBER: 934 +>>>>>>> ea605c16d (test build) +======= + VERSION_NUMBER: 935 +>>>>>>> 78ed4db87 (new build mumber) - opts: is_expand: false ANDROID_APK_LINK: '' diff --git a/ios/MetaMask.xcodeproj/project.pbxproj b/ios/MetaMask.xcodeproj/project.pbxproj index 397bbf51f05..8703c92f8ad 100644 --- a/ios/MetaMask.xcodeproj/project.pbxproj +++ b/ios/MetaMask.xcodeproj/project.pbxproj @@ -825,7 +825,15 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMaskDebug.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Manual; +<<<<<<< HEAD +<<<<<<< HEAD CURRENT_PROJECT_VERSION = 939; +======= + CURRENT_PROJECT_VERSION = 934; +>>>>>>> ea605c16d (test build) +======= + CURRENT_PROJECT_VERSION = 935; +>>>>>>> 78ed4db87 (new build mumber) DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = 48XVW22RCG; @@ -861,7 +869,11 @@ "\"$(SRCROOT)/MetaMask/System/Library/Frameworks\"", ); LLVM_LTO = YES; +<<<<<<< HEAD MARKETING_VERSION = 5.5.0; +======= + MARKETING_VERSION = 5.4.2; +>>>>>>> ea605c16d (test build) ONLY_ACTIVE_ARCH = YES; OTHER_CFLAGS = ( "$(inherited)", diff --git a/locales/languages/en.json b/locales/languages/en.json index 51748790b00..c5653996282 100644 --- a/locales/languages/en.json +++ b/locales/languages/en.json @@ -1204,10 +1204,6 @@ "enable_device_passcode_ios": "Unlock with device passcode?", "enable_device_passcode_android": "Unlock with device PIN?" }, - "remember_me": { - "enable_remember_me": "Allow \"Remember me\"", - "enable_remember_me_description": "Turn on at your own risk. When \"Remember me\" is on, it gives anyone access to your MetaMask if they can access your phone." - }, "authentication": { "auth_prompt_title": "Authentication required", "auth_prompt_desc": "Please authenticate in order to use MetaMask", diff --git a/package.json b/package.json index b73ff064dc8..b44a67d16b3 100644 --- a/package.json +++ b/package.json @@ -168,6 +168,7 @@ "is-url": "^1.2.4", "json-rpc-engine": "^6.1.0", "json-rpc-middleware-stream": "3.0.0", + "lodash": "^4.17.21", "lottie-react-native": "git+https://github.com/MetaMask/lottie-react-native.git#7ce6a78ac4ac7b9891bc513cb3f12f8b9c9d9106", "metro-config": "^0.71.1", "multihashes": "0.4.14", @@ -278,8 +279,10 @@ "@testing-library/react-hooks": "^8.0.1", "@types/enzyme": "^3.10.9", "@types/jest": "^27.0.1", + "@types/lodash": "^4.14.182", "@types/react": "^17.0.11", "@types/react-native": "^0.64.10", + "@types/react-native-material-textfield": "^0.16.5", "@types/react-native-vector-icons": "^6.4.8", "@types/react-native-video": "^5.0.13", "@types/redux-mock-store": "^1.0.3", diff --git a/yarn.lock b/yarn.lock index 3931a99890a..ccfc30a8d38 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3662,6 +3662,11 @@ dependencies: "@types/node" "*" +"@types/lodash@^4.14.182": + version "4.14.182" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.182.tgz#05301a4d5e62963227eaafe0ce04dd77c54ea5c2" + integrity sha512-/THyiqyQAP9AfARo4pF+aCGcyiQ94tX/Is2I7HofNRqoYLgN1PBoOWu2/zTA5zMxzP5EFutMtWtGAFRKUe961Q== + "@types/node@*": version "16.0.1" resolved "https://registry.yarnpkg.com/@types/node/-/node-16.0.1.tgz#70cedfda26af7a2ca073fdcc9beb2fff4aa693f8" @@ -3714,6 +3719,14 @@ "@types/react" "*" "@types/reactcss" "*" +"@types/react-native-material-textfield@^0.16.5": + version "0.16.5" + resolved "https://registry.yarnpkg.com/@types/react-native-material-textfield/-/react-native-material-textfield-0.16.5.tgz#fe91ef6339c282668f6eae24ca09a69f0a974974" + integrity sha512-QS3QzYiIE8DcaMp0ZALI3CQYsSn2mC8jjJAcbDleDfMeQ3+CD49kRpvKRKrgBkq7n4eRTZ2/KvaEKvb12sJ7Iw== + dependencies: + "@types/react" "*" + "@types/react-native" "*" + "@types/react-native-vector-icons@^6.4.8": version "6.4.8" resolved "https://registry.yarnpkg.com/@types/react-native-vector-icons/-/react-native-vector-icons-6.4.8.tgz#7dd9740f36a71e98c484b9ea12155940c85cedc2" From 217a0fc00b99c03acbe140dd4a868b7a5e51fde7 Mon Sep 17 00:00:00 2001 From: owencraston Date: Wed, 3 Aug 2022 17:49:56 -0400 Subject: [PATCH 04/17] remove LoginOptionsSwitch internal state - pass state value along with update callback to component --- .../LoginOptionsSwitch.test.tsx | 3 ++- .../LoginOptionsSwitch/LoginOptionsSwitch.tsx | 20 +++++++++---------- .../LoginOptionsSwitch.test.tsx.snap | 2 +- app/components/Views/ChoosePassword/index.js | 2 +- app/components/Views/ImportFromSeed/index.js | 2 +- app/components/Views/Login/index.js | 11 +--------- app/components/Views/ResetPassword/index.js | 2 +- bitrise.yml | 11 ---------- ios/MetaMask.xcodeproj/project.pbxproj | 12 ----------- ios/Podfile.lock | 2 +- 10 files changed, 17 insertions(+), 50 deletions(-) diff --git a/app/components/UI/LoginOptionsSwitch/LoginOptionsSwitch.test.tsx b/app/components/UI/LoginOptionsSwitch/LoginOptionsSwitch.test.tsx index e9f301c780d..e47368b24c0 100644 --- a/app/components/UI/LoginOptionsSwitch/LoginOptionsSwitch.test.tsx +++ b/app/components/UI/LoginOptionsSwitch/LoginOptionsSwitch.test.tsx @@ -14,7 +14,7 @@ describe('LoginWithBiometricsSwitch', () => { @@ -30,6 +30,7 @@ describe('LoginWithBiometricsSwitch', () => { , ); diff --git a/app/components/UI/LoginOptionsSwitch/LoginOptionsSwitch.tsx b/app/components/UI/LoginOptionsSwitch/LoginOptionsSwitch.tsx index 4e9c1ace4ad..b7b0c218048 100644 --- a/app/components/UI/LoginOptionsSwitch/LoginOptionsSwitch.tsx +++ b/app/components/UI/LoginOptionsSwitch/LoginOptionsSwitch.tsx @@ -12,7 +12,7 @@ import { useSelector } from 'react-redux'; interface Props { shouldRenderBiometricOption: BIOMETRY_TYPE | null; - initialBiometryChoice: boolean; + biometryChoiceState: boolean; onUpdateBiometryChoice: (biometryEnabled: boolean) => void; onUpdateRememberMe: (rememberMeEnabled: boolean) => void; } @@ -25,7 +25,7 @@ interface Props { */ const LoginOptionsSwitch = ({ shouldRenderBiometricOption, - initialBiometryChoice, + biometryChoiceState, onUpdateBiometryChoice, onUpdateRememberMe, }: Props) => { @@ -34,15 +34,13 @@ const LoginOptionsSwitch = ({ const allowLoginWithRememberMe = useSelector( (state: any) => state.security.allowLoginWithRememberMe, ); - const [biometryEnabled, setBiometryEnabled] = useState( - initialBiometryChoice, - ); const [rememberMeEnabled, setRememberMeEnabled] = useState(false); - - const onBiometryValueChanged = useCallback(async () => { - onUpdateBiometryChoice(!biometryEnabled); - setBiometryEnabled(!biometryEnabled); - }, [biometryEnabled, onUpdateBiometryChoice]); + const onBiometryValueChanged = useCallback( + async (newBiometryChoice: boolean) => { + onUpdateBiometryChoice(newBiometryChoice); + }, + [onUpdateBiometryChoice], + ); const onRememberMeValueChanged = useCallback(async () => { onUpdateRememberMe(!rememberMeEnabled); @@ -61,7 +59,7 @@ const LoginOptionsSwitch = ({ diff --git a/app/components/Views/ImportFromSeed/index.js b/app/components/Views/ImportFromSeed/index.js index 739e0bbc8bc..a6d25a8884d 100644 --- a/app/components/Views/ImportFromSeed/index.js +++ b/app/components/Views/ImportFromSeed/index.js @@ -457,7 +457,7 @@ class ImportFromSeed extends PureComponent { return ( diff --git a/app/components/Views/Login/index.js b/app/components/Views/Login/index.js index a7273d99204..120284c2ab4 100644 --- a/app/components/Views/Login/index.js +++ b/app/components/Views/Login/index.js @@ -457,15 +457,6 @@ class Login extends PureComponent { this.setState({ biometryChoice }); }; - updateBiometryChoice = async (biometryChoice) => { - if (!biometryChoice) { - await AsyncStorage.setItem(BIOMETRY_CHOICE_DISABLED, TRUE); - } else { - await AsyncStorage.removeItem(BIOMETRY_CHOICE_DISABLED); - } - this.setState({ biometryChoice }); - }; - renderSwitch = () => { const handleUpdateRememberMe = (rememberMe) => { this.setState({ rememberMe }); @@ -477,7 +468,7 @@ class Login extends PureComponent { return ( diff --git a/app/components/Views/ResetPassword/index.js b/app/components/Views/ResetPassword/index.js index c0de48a8941..b575d8db99d 100644 --- a/app/components/Views/ResetPassword/index.js +++ b/app/components/Views/ResetPassword/index.js @@ -547,7 +547,7 @@ class ResetPassword extends PureComponent { return ( diff --git a/bitrise.yml b/bitrise.yml index 4b6ac910461..9ca1343e01b 100644 --- a/bitrise.yml +++ b/bitrise.yml @@ -323,21 +323,10 @@ app: PROJECT_LOCATION_IOS: ios - opts: is_expand: false -<<<<<<< HEAD VERSION_NAME: 5.5.0 - opts: is_expand: false VERSION_NUMBER: 939 -======= - VERSION_NAME: 5.4.2 - - opts: - is_expand: false -<<<<<<< HEAD - VERSION_NUMBER: 934 ->>>>>>> ea605c16d (test build) -======= - VERSION_NUMBER: 935 ->>>>>>> 78ed4db87 (new build mumber) - opts: is_expand: false ANDROID_APK_LINK: '' diff --git a/ios/MetaMask.xcodeproj/project.pbxproj b/ios/MetaMask.xcodeproj/project.pbxproj index 8703c92f8ad..397bbf51f05 100644 --- a/ios/MetaMask.xcodeproj/project.pbxproj +++ b/ios/MetaMask.xcodeproj/project.pbxproj @@ -825,15 +825,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMaskDebug.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Manual; -<<<<<<< HEAD -<<<<<<< HEAD CURRENT_PROJECT_VERSION = 939; -======= - CURRENT_PROJECT_VERSION = 934; ->>>>>>> ea605c16d (test build) -======= - CURRENT_PROJECT_VERSION = 935; ->>>>>>> 78ed4db87 (new build mumber) DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = 48XVW22RCG; @@ -869,11 +861,7 @@ "\"$(SRCROOT)/MetaMask/System/Library/Frameworks\"", ); LLVM_LTO = YES; -<<<<<<< HEAD MARKETING_VERSION = 5.5.0; -======= - MARKETING_VERSION = 5.4.2; ->>>>>>> ea605c16d (test build) ONLY_ACTIVE_ARCH = YES; OTHER_CFLAGS = ( "$(inherited)", diff --git a/ios/Podfile.lock b/ios/Podfile.lock index a4881dfa174..b9855a51b93 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -841,4 +841,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: 5759da19ce141e5f8aca3a4f56ac232baa34e957 -COCOAPODS: 1.11.2 +COCOAPODS: 1.11.3 From 5fdea7268986f2c595cb042f80e33a5600b34182 Mon Sep 17 00:00:00 2001 From: owencraston Date: Wed, 10 Aug 2022 12:21:51 -0400 Subject: [PATCH 05/17] translations --- locales/languages/de.json | 10 ++++++++++ locales/languages/el.json | 10 ++++++++++ locales/languages/es.json | 10 ++++++++++ locales/languages/fr.json | 10 ++++++++++ locales/languages/hi.json | 10 ++++++++++ locales/languages/id.json | 10 ++++++++++ locales/languages/ja.json | 10 ++++++++++ locales/languages/ko.json | 10 ++++++++++ locales/languages/pt.json | 10 ++++++++++ locales/languages/ru.json | 10 ++++++++++ locales/languages/tl.json | 10 ++++++++++ locales/languages/tr.json | 10 ++++++++++ locales/languages/vi.json | 10 ++++++++++ locales/languages/zh.json | 10 ++++++++++ 14 files changed, 140 insertions(+) diff --git a/locales/languages/de.json b/locales/languages/de.json index c728007b4b8..73573597a1c 100644 --- a/locales/languages/de.json +++ b/locales/languages/de.json @@ -1996,5 +1996,15 @@ "token_detection_mainnet_title": "Die Token-Erkennung ist aktiviert, so dass viele Token automatisch in Ihrem Wallet auftauchen werden.", "token_detection_mainnet_link": "Sie können Token auch manuell hinzufügen.", "or": "oder" + }, + "remember_me": { + "enable_remember_me": "„Angemeldet bleiben“ aktivieren", + "enable_remember_me_description": "Wenn „Angemeldet bleiben“ aktiviert ist, kann jeder, der Zugriff zu Ihrem Handy hat, auf Ihr MetaMask-Konto zugreifen." + }, + "turn_off_remember_me": { + "title": "Geben Sie Ihr Passwort ein, um „Angemeldet bleiben“ zu deaktivieren", + "placeholder": "Passwort", + "description": "Wenn Sie diese Option deaktivieren, benötigen Sie von jetzt an Ihr Passwort, um MetaMask zu entsperren.", + "action": "„Angemeldet bleiben“ deaktivieren" } } diff --git a/locales/languages/el.json b/locales/languages/el.json index 2606a137d67..178a6c713d9 100644 --- a/locales/languages/el.json +++ b/locales/languages/el.json @@ -1996,5 +1996,15 @@ "token_detection_mainnet_title": "Ο εντοπισμός token είναι ενεργοποιημένος και πολλά token θα εμφανιστούν αυτόματα στο πορτοφόλι σας.", "token_detection_mainnet_link": "Μπορείτε επίσης να προσθέσετε token μη αυτόματα.", "or": "ή" + }, + "remember_me": { + "enable_remember_me": "Δοκιμάστε να ενεργοποιήσετε το Θυμήσου με", + "enable_remember_me_description": "Όταν το «Θυμήσου με» είναι ενεργοποιημένο, οποιοσδήποτε με πρόσβαση στο κινητό σας μπορεί να έχει πρόσβαση στον λογαριασμό σας MetaMask." + }, + "turn_off_remember_me": { + "title": "Εισαγάγετε τον κωδικό πρόσβασής σας για να απενεργοποιήσετε το «Θυμήσου με»", + "placeholder": "Κωδικός πρόσβασης", + "description": "Εάν απενεργοποιήσετε αυτή την επιλογή, από εδώ και πέρα θα χρειάζεστε τον κωδικό πρόσβασής σας για να ξεκλειδώσετε το MetaMask.", + "action": "Απενεργοποίηση του «Θυμήσου με»" } } diff --git a/locales/languages/es.json b/locales/languages/es.json index 109c5fcbfee..c85e8634742 100644 --- a/locales/languages/es.json +++ b/locales/languages/es.json @@ -1996,5 +1996,15 @@ "token_detection_mainnet_title": "La detección de tokens está habilitada, por lo que muchos aparecerán automáticamente en su billetera.", "token_detection_mainnet_link": "También puede agregar los tokens manualmente.", "or": "o" + }, + "remember_me": { + "enable_remember_me": "Activar Recordarme", + "enable_remember_me_description": "Cuando Recordarme está activado, cualquier persona con acceso a su teléfono puede acceder a su cuenta de MetaMask." + }, + "turn_off_remember_me": { + "title": "Ingrese su contraseña para desactivar Recordarme", + "placeholder": "Contraseña", + "description": "Si desactiva esta opción, necesitará su contraseña para desbloquear MetaMask de ahora en adelante.", + "action": "Desactivar Recordarme" } } diff --git a/locales/languages/fr.json b/locales/languages/fr.json index bffdce15cbf..aff5f6bd9c4 100644 --- a/locales/languages/fr.json +++ b/locales/languages/fr.json @@ -1996,5 +1996,15 @@ "token_detection_mainnet_title": "La détection des jetons est activée, ce qui signifie que de nombreux jetons apparaîtront automatiquement dans votre portefeuille.", "token_detection_mainnet_link": "Vous pouvez également ajouter des jetons manuellement.", "or": "ou" + }, + "remember_me": { + "enable_remember_me": "Activer l'option « Se souvenir de moi »", + "enable_remember_me_description": "Lorsque l'option « Se souvenir de moi » est activée, toute personne ayant accès à votre téléphone peut accéder à votre compte MetaMask." + }, + "turn_off_remember_me": { + "title": "Saisissez votre mot de passe pour désactiver l'option « Se souvenir de moi »", + "placeholder": "Mot de passe", + "description": "Si vous désactivez cette option, la saisie du mot de passe sera requise pour déverrouiller MetaMask.", + "action": "Désactiver l'option « Se souvenir de moi »" } } diff --git a/locales/languages/hi.json b/locales/languages/hi.json index 7590edae8b2..ec44bf56e02 100644 --- a/locales/languages/hi.json +++ b/locales/languages/hi.json @@ -1996,5 +1996,15 @@ "token_detection_mainnet_title": "Token detection is enabled so many tokens will automatically show up in your wallet.", "token_detection_mainnet_link": "You can also add tokens manually.", "or": "or" + }, + "remember_me": { + "enable_remember_me": "रिमेंबर मी चालू करें", + "enable_remember_me_description": "जब रिमेंबर मी चालू रहेगा, आपका फोन एक्सेस करने वाला कोई भी व्यक्ति आपके MetaMask अकाउंट को एक्सेस कर सकता है।" + }, + "turn_off_remember_me": { + "title": "रिमेंबर मी को बंद करने के लिए अपना पासवर्ड दर्ज करें", + "placeholder": "पासवर्ड", + "description": "अगर आप इस ऑप्शन को बंद करते हैं, तो अब से आपको MetaMask अनलॉक करने के लिए अपने पासवर्ड की ज़रूरत होगी।", + "action": "रिमेंबर मी बंद करें" } } diff --git a/locales/languages/id.json b/locales/languages/id.json index 5453eb68af3..f5225d49628 100644 --- a/locales/languages/id.json +++ b/locales/languages/id.json @@ -1996,5 +1996,15 @@ "token_detection_mainnet_title": "Deteksi token diaktifkan sehingga banyak token akan muncul di dompet Anda secara otomatis.", "token_detection_mainnet_link": "Anda juga dapat menambahkan token secara manual.", "or": "atau" + }, + "remember_me": { + "enable_remember_me": "Aktifkan Ingatkan saya", + "enable_remember_me_description": "Saat Ingatkan saya aktif, siapa pun yang memiliki akses ke ponsel Anda dapat mengakses akun MetaMask Anda." + }, + "turn_off_remember_me": { + "title": "Masukkan kata sandi Anda untuk menonaktifkan Ingatkan saya", + "placeholder": "Kata sandi", + "description": "Jika Anda menonaktifkan opsi ini, Anda memerlukan kata sandi untuk membuka MetaMask mulai sekarang.", + "action": "Nonaktifkan Ingatkan saya" } } diff --git a/locales/languages/ja.json b/locales/languages/ja.json index deff30532b4..1e88e058015 100644 --- a/locales/languages/ja.json +++ b/locales/languages/ja.json @@ -1996,5 +1996,15 @@ "token_detection_mainnet_title": "トークン検出が有効になっているため、多くのトークンが自動的にウォレットに表示されます。", "token_detection_mainnet_link": "手動でトークンを追加することもできます。", "or": "または" + }, + "remember_me": { + "enable_remember_me": "認証情報の保存を有効にする", + "enable_remember_me_description": "認証情報の保存を有効にすると、携帯にアクセスできる人は誰でも MetaMask アカウントにアクセスできるようになります。" + }, + "turn_off_remember_me": { + "title": "認証情報の保存を無効にするには、パスワードを入力してください", + "placeholder": "パスワード", + "description": "このオプションを無効にすると、今後 MetaMask のロックを解除するのにパスワードが必要になります。", + "action": "認証情報の保存を無効にする" } } diff --git a/locales/languages/ko.json b/locales/languages/ko.json index 4dba3d3eb73..8d1e0ffb0d4 100644 --- a/locales/languages/ko.json +++ b/locales/languages/ko.json @@ -1996,5 +1996,15 @@ "token_detection_mainnet_title": "토큰 감지가 활성화되어 여러 토큰이 자동으로 지갑에 나타납니다.", "token_detection_mainnet_link": "또한 수동으로 토큰을 추가할 수도 있습니다.", "or": "또는" + }, + "remember_me": { + "enable_remember_me": "로그인 정보 저장", + "enable_remember_me_description": "로그인 정보를 저장하면 회원님의 휴대폰을 이용하는 모든 사람이 회원님의 MetaMask 계정에 액세스할 수 있습니다." + }, + "turn_off_remember_me": { + "title": "로그인 정보 저장 기능을 끄려면 비밀번호를 입력하세요", + "placeholder": "비밀번호", + "description": "이 기능을 끄면 지금부터 비밀번호를 사용하여 MetaMask를 잠금 해제해야 합니다.", + "action": "로그인 정보 저장 끄기" } } diff --git a/locales/languages/pt.json b/locales/languages/pt.json index 91dda89691e..0b1e5a8a834 100644 --- a/locales/languages/pt.json +++ b/locales/languages/pt.json @@ -1996,5 +1996,15 @@ "token_detection_mainnet_title": "Com a detecção ativada, muitos tokens serão automaticamente exibidos em sua carteira.", "token_detection_mainnet_link": "Você também pode adicionar tokens manualmente.", "or": "ou" + }, + "remember_me": { + "enable_remember_me": "Ativar \"Lembrar de mim\"", + "enable_remember_me_description": "Quando \"Lembrar de mim\" estiver ativado, qualquer pessoa com acesso ao seu telefone poderá acessar sua conta da MetaMask." + }, + "turn_off_remember_me": { + "title": "Insira sua senha para desativar \"Lembrar de mim\"", + "placeholder": "Senha", + "description": "Se desativar essa opção, você precisará de sua senha para desbloquear a MetaMask a partir de agora.", + "action": "Desativar \"Lembrar de mim\"" } } diff --git a/locales/languages/ru.json b/locales/languages/ru.json index f8232b79fe0..9d3853401ea 100644 --- a/locales/languages/ru.json +++ b/locales/languages/ru.json @@ -1996,5 +1996,15 @@ "token_detection_mainnet_title": "Обнаружение токенов включено, поэтому многие токены автоматически появятся в вашем кошельке.", "token_detection_mainnet_link": "Вы также можете добавлять токены вручную.", "or": "или" + }, + "remember_me": { + "enable_remember_me": "Включить \"Запомнить меня\"", + "enable_remember_me_description": "Когда функция \"Запомнить меня\" включена, любой, у кого есть доступ к вашему телефону, может получить доступ к вашему счету MetaMask." + }, + "turn_off_remember_me": { + "title": "Введите пароль, чтобы отключить \"Запомнить меня\"", + "placeholder": "Пароль", + "description": "Если вы отключите эту опцию, с этого момента вам потребуется пароль для разблокировки MetaMask.", + "action": "Выключить \"Запомнить меня\"" } } diff --git a/locales/languages/tl.json b/locales/languages/tl.json index d9e3d864a24..6c96edc0f0d 100644 --- a/locales/languages/tl.json +++ b/locales/languages/tl.json @@ -1996,5 +1996,15 @@ "token_detection_mainnet_title": "Pinagana ang pagtuklas ng token kaya maraming mga token ang awtomatikong lalabas sa iyong wallet.", "token_detection_mainnet_link": "Maaari ka ring magdagdag ng mga token ng manu-mano.", "or": "o" + }, + "remember_me": { + "enable_remember_me": "I-on ang Tandaan ako", + "enable_remember_me_description": "Kapag naka-on ang tandaan ako, sinumang may access sa iyong telepono ay makaka-access sa iyong MetaMask account." + }, + "turn_off_remember_me": { + "title": "Ilagay ang iyong password para i-off ang Tandaan ako", + "placeholder": "Password", + "description": "Kung in-off mo ang opsyong ito, kakailanganin mo ang iyong password upang i-unlock ang MetaMask mula ngayon.", + "action": "I-off ang Tandaan ako" } } diff --git a/locales/languages/tr.json b/locales/languages/tr.json index c3dacabdd60..648f1c69090 100644 --- a/locales/languages/tr.json +++ b/locales/languages/tr.json @@ -1996,5 +1996,15 @@ "token_detection_mainnet_title": "Token algılama etkinleştirildi böylece pek çok token otomatik olarak cüzdanınızda gösterilecek.", "token_detection_mainnet_link": "Manuel olarak da ekleyebilirsiniz.", "or": "veya" + }, + "remember_me": { + "enable_remember_me": "Beni Hatırla özelliğini aç", + "enable_remember_me_description": "Beni Hatırla özelliği açıldığında telefonunuza erişimi olan herkes MetaMask hesabınıza erişim sağlayabilir." + }, + "turn_off_remember_me": { + "title": "Beni Hatırla özelliğini kapatmak için parolanızı girin", + "placeholder": "Parola", + "description": "Bu seçeneği kapatırsanız şu andan itibaren MetaMask'in kilidini açmak için şifrenizi girmeniz gerekecektir.", + "action": "Beni Hatırla özelliğini kapat" } } diff --git a/locales/languages/vi.json b/locales/languages/vi.json index d45dc32451a..2a80c1576f3 100644 --- a/locales/languages/vi.json +++ b/locales/languages/vi.json @@ -1996,5 +1996,15 @@ "token_detection_mainnet_title": "Đã bật tính năng phát hiện token nên nhiều token sẽ tự động hiển thị trong ví của bạn.", "token_detection_mainnet_link": "Bạn cũng có thể thêm token theo cách thủ công.", "or": "hoặc" + }, + "remember_me": { + "enable_remember_me": "Bật Ghi nhớ", + "enable_remember_me_description": "Khi bật Ghi nhớ, bất kỳ ai có quyền truy cập vào điện thoại của bạn đều có thể truy cập vào tài khoản MetaMask của bạn." + }, + "turn_off_remember_me": { + "title": "Nhập mật khẩu để tắt Ghi nhớ", + "placeholder": "Mật khẩu", + "description": "Nếu bạn tắt tùy chọn này, bạn sẽ cần nhập mật khẩu để mở khóa MetaMask kể từ bây giờ.", + "action": "Tắt Ghi nhớ" } } diff --git a/locales/languages/zh.json b/locales/languages/zh.json index d44ed57a42a..8c15677bb87 100644 --- a/locales/languages/zh.json +++ b/locales/languages/zh.json @@ -1996,5 +1996,15 @@ "token_detection_mainnet_title": "已启用代币检测,因此将会有许多代币自动显示在您的钱包中。", "token_detection_mainnet_link": "您也可以手动添加代币。", "or": "或" + }, + "remember_me": { + "enable_remember_me": "打开“记住我”", + "enable_remember_me_description": "在“记住我”功能打开时,任何有访问您手机权限的人都可以访问您的MetaMask账户。" + }, + "turn_off_remember_me": { + "title": "输入密码以关闭“记住我”", + "placeholder": "密码", + "description": "如果关闭此选项,从现在起,您需要使用密码来解锁MetaMask。", + "action": "关闭“记住我”" } } From 49f5e6e582cc1c17fc6e625481c343dbdca49203 Mon Sep 17 00:00:00 2001 From: owencraston Date: Wed, 10 Aug 2022 12:29:04 -0400 Subject: [PATCH 06/17] new test build --- android/app/build.gradle | 4 ++-- bitrise.yml | 4 ++-- ios/MetaMask.xcodeproj/project.pbxproj | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index f166a3e29b4..f7791e0186a 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -160,8 +160,8 @@ android { applicationId "io.metamask" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 939 - versionName "5.5.0" + versionCode 942 + versionName "5.4.2" multiDexEnabled true testBuildType System.getProperty('testBuildType', 'debug') missingDimensionStrategy "minReactNative", "minReactNative46" diff --git a/bitrise.yml b/bitrise.yml index 9ca1343e01b..a35b6eb501c 100644 --- a/bitrise.yml +++ b/bitrise.yml @@ -323,10 +323,10 @@ app: PROJECT_LOCATION_IOS: ios - opts: is_expand: false - VERSION_NAME: 5.5.0 + VERSION_NAME: 5.4.2 - opts: is_expand: false - VERSION_NUMBER: 939 + VERSION_NUMBER: 942 - opts: is_expand: false ANDROID_APK_LINK: '' diff --git a/ios/MetaMask.xcodeproj/project.pbxproj b/ios/MetaMask.xcodeproj/project.pbxproj index 397bbf51f05..17ab7e1f122 100644 --- a/ios/MetaMask.xcodeproj/project.pbxproj +++ b/ios/MetaMask.xcodeproj/project.pbxproj @@ -825,7 +825,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMaskDebug.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 939; + CURRENT_PROJECT_VERSION = 942; DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = 48XVW22RCG; @@ -861,7 +861,7 @@ "\"$(SRCROOT)/MetaMask/System/Library/Frameworks\"", ); LLVM_LTO = YES; - MARKETING_VERSION = 5.5.0; + MARKETING_VERSION = 5.4.2; ONLY_ACTIVE_ARCH = YES; OTHER_CFLAGS = ( "$(inherited)", @@ -892,7 +892,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMask.entitlements; CODE_SIGN_IDENTITY = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 939; + CURRENT_PROJECT_VERSION = 942; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = 48XVW22RCG; FRAMEWORK_SEARCH_PATHS = ( @@ -927,7 +927,7 @@ "\"$(SRCROOT)/MetaMask/System/Library/Frameworks\"", ); LLVM_LTO = YES; - MARKETING_VERSION = 5.5.0; + MARKETING_VERSION = 5.4.2; ONLY_ACTIVE_ARCH = NO; OTHER_CFLAGS = ( "$(inherited)", From a879be52e3f2bbb8d0b09ec1a8ec40c08b32564d Mon Sep 17 00:00:00 2001 From: owencraston Date: Fri, 12 Aug 2022 12:56:43 -0400 Subject: [PATCH 07/17] new test component --- .../TurnOffRememberMeModal.tsx | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/app/components/UI/TurnOffRememberMeModal/TurnOffRememberMeModal.tsx b/app/components/UI/TurnOffRememberMeModal/TurnOffRememberMeModal.tsx index 53b49b9371e..4c85c551440 100644 --- a/app/components/UI/TurnOffRememberMeModal/TurnOffRememberMeModal.tsx +++ b/app/components/UI/TurnOffRememberMeModal/TurnOffRememberMeModal.tsx @@ -1,8 +1,6 @@ import React, { useState, useRef, useCallback } from 'react'; import { View, TouchableWithoutFeedback, Keyboard } from 'react-native'; -import BaseText, { - BaseTextVariant, -} from '../../../component-library/components/BaseText'; +import Text, { TextVariant } from '../../../component-library/components/Text'; import { OutlinedTextField } from 'react-native-material-textfield'; import { createStyles } from './styles'; import ReusableModal, { ReusableModalRef } from '../ReusableModal'; @@ -86,18 +84,12 @@ const TurnOffRememberMeModal = () => { > - + {strings('turn_off_remember_me.title')} - - + + {strings('turn_off_remember_me.description')} - + Date: Fri, 12 Aug 2022 14:30:05 -0400 Subject: [PATCH 08/17] remove build --- android/app/build.gradle | 4 ++-- bitrise.yml | 4 ++-- ios/MetaMask.xcodeproj/project.pbxproj | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index f7791e0186a..f166a3e29b4 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -160,8 +160,8 @@ android { applicationId "io.metamask" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 942 - versionName "5.4.2" + versionCode 939 + versionName "5.5.0" multiDexEnabled true testBuildType System.getProperty('testBuildType', 'debug') missingDimensionStrategy "minReactNative", "minReactNative46" diff --git a/bitrise.yml b/bitrise.yml index a35b6eb501c..9ca1343e01b 100644 --- a/bitrise.yml +++ b/bitrise.yml @@ -323,10 +323,10 @@ app: PROJECT_LOCATION_IOS: ios - opts: is_expand: false - VERSION_NAME: 5.4.2 + VERSION_NAME: 5.5.0 - opts: is_expand: false - VERSION_NUMBER: 942 + VERSION_NUMBER: 939 - opts: is_expand: false ANDROID_APK_LINK: '' diff --git a/ios/MetaMask.xcodeproj/project.pbxproj b/ios/MetaMask.xcodeproj/project.pbxproj index 17ab7e1f122..397bbf51f05 100644 --- a/ios/MetaMask.xcodeproj/project.pbxproj +++ b/ios/MetaMask.xcodeproj/project.pbxproj @@ -825,7 +825,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMaskDebug.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 942; + CURRENT_PROJECT_VERSION = 939; DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = 48XVW22RCG; @@ -861,7 +861,7 @@ "\"$(SRCROOT)/MetaMask/System/Library/Frameworks\"", ); LLVM_LTO = YES; - MARKETING_VERSION = 5.4.2; + MARKETING_VERSION = 5.5.0; ONLY_ACTIVE_ARCH = YES; OTHER_CFLAGS = ( "$(inherited)", @@ -892,7 +892,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMask.entitlements; CODE_SIGN_IDENTITY = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 942; + CURRENT_PROJECT_VERSION = 939; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = 48XVW22RCG; FRAMEWORK_SEARCH_PATHS = ( @@ -927,7 +927,7 @@ "\"$(SRCROOT)/MetaMask/System/Library/Frameworks\"", ); LLVM_LTO = YES; - MARKETING_VERSION = 5.4.2; + MARKETING_VERSION = 5.5.0; ONLY_ACTIVE_ARCH = NO; OTHER_CFLAGS = ( "$(inherited)", From 36fc57d48ff89e79f8265f151a6539c81c16d26f Mon Sep 17 00:00:00 2001 From: owencraston Date: Mon, 15 Aug 2022 06:36:30 -0700 Subject: [PATCH 09/17] safe area view --- android/.project | 11 +++ .../org.eclipse.buildship.core.prefs | 11 +++ .../TurnOffRememberMeModal.tsx | 81 ++++++++++--------- .../UI/TurnOffRememberMeModal/styles.ts | 3 + ios/Podfile.lock | 2 +- 5 files changed, 70 insertions(+), 38 deletions(-) diff --git a/android/.project b/android/.project index 3cf8618bf4c..4306ec3ec43 100644 --- a/android/.project +++ b/android/.project @@ -14,4 +14,15 @@ org.eclipse.buildship.core.gradleprojectnature + + + 1660332918632 + + 30 + + org.eclipse.core.resources.regexFilterMatcher + node_modules|.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ + + + diff --git a/android/.settings/org.eclipse.buildship.core.prefs b/android/.settings/org.eclipse.buildship.core.prefs index e8895216fd3..e479558406c 100644 --- a/android/.settings/org.eclipse.buildship.core.prefs +++ b/android/.settings/org.eclipse.buildship.core.prefs @@ -1,2 +1,13 @@ +arguments= +auto.sync=false +build.scans.enabled=false +connection.gradle.distribution=GRADLE_DISTRIBUTION(WRAPPER) connection.project.dir= eclipse.preferences.version=1 +gradle.user.home= +java.home= +jvm.arguments= +offline.mode=false +override.workspace.settings=false +show.console.view=false +show.executions.view=false diff --git a/app/components/UI/TurnOffRememberMeModal/TurnOffRememberMeModal.tsx b/app/components/UI/TurnOffRememberMeModal/TurnOffRememberMeModal.tsx index 4c85c551440..12b9fa3c31a 100644 --- a/app/components/UI/TurnOffRememberMeModal/TurnOffRememberMeModal.tsx +++ b/app/components/UI/TurnOffRememberMeModal/TurnOffRememberMeModal.tsx @@ -1,5 +1,10 @@ import React, { useState, useRef, useCallback } from 'react'; -import { View, TouchableWithoutFeedback, Keyboard } from 'react-native'; +import { + View, + TouchableWithoutFeedback, + Keyboard, + SafeAreaView, +} from 'react-native'; import Text, { TextVariant } from '../../../component-library/components/Text'; import { OutlinedTextField } from 'react-native-material-textfield'; import { createStyles } from './styles'; @@ -73,42 +78,44 @@ const TurnOffRememberMeModal = () => { }, [turnOffRememberMeAndLockApp]); return ( - - - - - - {strings('turn_off_remember_me.title')} - - - {strings('turn_off_remember_me.description')} - - - - - - + + + + + + + {strings('turn_off_remember_me.title')} + + + {strings('turn_off_remember_me.description')} + + + + + + + ); }; diff --git a/app/components/UI/TurnOffRememberMeModal/styles.ts b/app/components/UI/TurnOffRememberMeModal/styles.ts index 35a9dd887d2..352222f18d3 100644 --- a/app/components/UI/TurnOffRememberMeModal/styles.ts +++ b/app/components/UI/TurnOffRememberMeModal/styles.ts @@ -7,6 +7,9 @@ const breakPoint = Device.getDeviceHeight() < 700; export const createStyles = (colors: any) => StyleSheet.create({ + container: { + flex: 1, + }, areYouSure: { width: '100%', padding: breakPoint ? 16 : 24, diff --git a/ios/Podfile.lock b/ios/Podfile.lock index b9855a51b93..a4881dfa174 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -841,4 +841,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: 5759da19ce141e5f8aca3a4f56ac232baa34e957 -COCOAPODS: 1.11.3 +COCOAPODS: 1.11.2 From 915e30600d5dabd7e5e825b64bb77b97c7164893 Mon Sep 17 00:00:00 2001 From: owencraston Date: Mon, 15 Aug 2022 08:33:47 -0700 Subject: [PATCH 10/17] wrapped modal --- .../UI/TurnOffRememberMeModal/TurnOffRememberMeModal.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/components/UI/TurnOffRememberMeModal/TurnOffRememberMeModal.tsx b/app/components/UI/TurnOffRememberMeModal/TurnOffRememberMeModal.tsx index 12b9fa3c31a..e374877274a 100644 --- a/app/components/UI/TurnOffRememberMeModal/TurnOffRememberMeModal.tsx +++ b/app/components/UI/TurnOffRememberMeModal/TurnOffRememberMeModal.tsx @@ -78,8 +78,8 @@ const TurnOffRememberMeModal = () => { }, [turnOffRememberMeAndLockApp]); return ( - - + + { - - + + ); }; From 2726907074669c7d2d859236645377a9e18dd9cb Mon Sep 17 00:00:00 2001 From: owencraston Date: Mon, 15 Aug 2022 08:39:47 -0700 Subject: [PATCH 11/17] new test build --- android/app/build.gradle | 4 ++-- bitrise.yml | 4 ++-- ios/MetaMask.xcodeproj/project.pbxproj | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index f166a3e29b4..0282b189932 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -160,8 +160,8 @@ android { applicationId "io.metamask" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 939 - versionName "5.5.0" + versionCode 947 + versionName "5.4.2" multiDexEnabled true testBuildType System.getProperty('testBuildType', 'debug') missingDimensionStrategy "minReactNative", "minReactNative46" diff --git a/bitrise.yml b/bitrise.yml index 9ca1343e01b..2d987e69b6c 100644 --- a/bitrise.yml +++ b/bitrise.yml @@ -323,10 +323,10 @@ app: PROJECT_LOCATION_IOS: ios - opts: is_expand: false - VERSION_NAME: 5.5.0 + VERSION_NAME: 5.4.2 - opts: is_expand: false - VERSION_NUMBER: 939 + VERSION_NUMBER: 947 - opts: is_expand: false ANDROID_APK_LINK: '' diff --git a/ios/MetaMask.xcodeproj/project.pbxproj b/ios/MetaMask.xcodeproj/project.pbxproj index 397bbf51f05..37ad6905839 100644 --- a/ios/MetaMask.xcodeproj/project.pbxproj +++ b/ios/MetaMask.xcodeproj/project.pbxproj @@ -825,7 +825,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMaskDebug.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 939; + CURRENT_PROJECT_VERSION = 947; DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = 48XVW22RCG; @@ -861,7 +861,7 @@ "\"$(SRCROOT)/MetaMask/System/Library/Frameworks\"", ); LLVM_LTO = YES; - MARKETING_VERSION = 5.5.0; + MARKETING_VERSION = 5.4.2; ONLY_ACTIVE_ARCH = YES; OTHER_CFLAGS = ( "$(inherited)", @@ -892,7 +892,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMask.entitlements; CODE_SIGN_IDENTITY = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 939; + CURRENT_PROJECT_VERSION = 947; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = 48XVW22RCG; FRAMEWORK_SEARCH_PATHS = ( @@ -927,7 +927,7 @@ "\"$(SRCROOT)/MetaMask/System/Library/Frameworks\"", ); LLVM_LTO = YES; - MARKETING_VERSION = 5.5.0; + MARKETING_VERSION = 5.4.2; ONLY_ACTIVE_ARCH = NO; OTHER_CFLAGS = ( "$(inherited)", From d7b6ac77f43cdcb85bfd6eb72d14e1fa04ca46dd Mon Sep 17 00:00:00 2001 From: owencraston Date: Tue, 16 Aug 2022 08:15:10 -0700 Subject: [PATCH 12/17] new test build --- android/app/build.gradle | 2 +- bitrise.yml | 2 +- ios/MetaMask.xcodeproj/project.pbxproj | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 0282b189932..1d7841ab24d 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -160,7 +160,7 @@ android { applicationId "io.metamask" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 947 + versionCode 948 versionName "5.4.2" multiDexEnabled true testBuildType System.getProperty('testBuildType', 'debug') diff --git a/bitrise.yml b/bitrise.yml index 2d987e69b6c..0b462dce393 100644 --- a/bitrise.yml +++ b/bitrise.yml @@ -326,7 +326,7 @@ app: VERSION_NAME: 5.4.2 - opts: is_expand: false - VERSION_NUMBER: 947 + VERSION_NUMBER: 948 - opts: is_expand: false ANDROID_APK_LINK: '' diff --git a/ios/MetaMask.xcodeproj/project.pbxproj b/ios/MetaMask.xcodeproj/project.pbxproj index 37ad6905839..4a29c2e1db5 100644 --- a/ios/MetaMask.xcodeproj/project.pbxproj +++ b/ios/MetaMask.xcodeproj/project.pbxproj @@ -825,7 +825,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMaskDebug.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 947; + CURRENT_PROJECT_VERSION = 948; DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = 48XVW22RCG; @@ -892,7 +892,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMask.entitlements; CODE_SIGN_IDENTITY = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 947; + CURRENT_PROJECT_VERSION = 948; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = 48XVW22RCG; FRAMEWORK_SEARCH_PATHS = ( From af179c8d99f03e00a1501573a501e55abeb0057c Mon Sep 17 00:00:00 2001 From: owencraston Date: Tue, 16 Aug 2022 08:19:48 -0700 Subject: [PATCH 13/17] cleanup --- android/.project | 11 ----------- android/.settings/org.eclipse.buildship.core.prefs | 11 ----------- 2 files changed, 22 deletions(-) diff --git a/android/.project b/android/.project index 4306ec3ec43..3cf8618bf4c 100644 --- a/android/.project +++ b/android/.project @@ -14,15 +14,4 @@ org.eclipse.buildship.core.gradleprojectnature - - - 1660332918632 - - 30 - - org.eclipse.core.resources.regexFilterMatcher - node_modules|.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ - - - diff --git a/android/.settings/org.eclipse.buildship.core.prefs b/android/.settings/org.eclipse.buildship.core.prefs index e479558406c..e8895216fd3 100644 --- a/android/.settings/org.eclipse.buildship.core.prefs +++ b/android/.settings/org.eclipse.buildship.core.prefs @@ -1,13 +1,2 @@ -arguments= -auto.sync=false -build.scans.enabled=false -connection.gradle.distribution=GRADLE_DISTRIBUTION(WRAPPER) connection.project.dir= eclipse.preferences.version=1 -gradle.user.home= -java.home= -jvm.arguments= -offline.mode=false -override.workspace.settings=false -show.console.view=false -show.executions.view=false From 92c7f58ef903fdba8685878e218c38a792386d16 Mon Sep 17 00:00:00 2001 From: owencraston Date: Tue, 16 Aug 2022 12:58:55 -0700 Subject: [PATCH 14/17] more space --- app/components/UI/TurnOffRememberMeModal/styles.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/components/UI/TurnOffRememberMeModal/styles.ts b/app/components/UI/TurnOffRememberMeModal/styles.ts index 352222f18d3..727c392fbfc 100644 --- a/app/components/UI/TurnOffRememberMeModal/styles.ts +++ b/app/components/UI/TurnOffRememberMeModal/styles.ts @@ -12,7 +12,7 @@ export const createStyles = (colors: any) => }, areYouSure: { width: '100%', - padding: breakPoint ? 16 : 24, + padding: breakPoint ? 16 : 32, justifyContent: 'center', alignSelf: 'center', }, From 9424df2042d104c3cb6a720767633246799c8350 Mon Sep 17 00:00:00 2001 From: owencraston Date: Tue, 16 Aug 2022 14:09:07 -0700 Subject: [PATCH 15/17] explicitly navigate to login --- .../UI/TurnOffRememberMeModal/TurnOffRememberMeModal.tsx | 9 +++++---- package.json | 2 -- yarn.lock | 5 ----- 3 files changed, 5 insertions(+), 11 deletions(-) diff --git a/app/components/UI/TurnOffRememberMeModal/TurnOffRememberMeModal.tsx b/app/components/UI/TurnOffRememberMeModal/TurnOffRememberMeModal.tsx index e374877274a..4d535388d8f 100644 --- a/app/components/UI/TurnOffRememberMeModal/TurnOffRememberMeModal.tsx +++ b/app/components/UI/TurnOffRememberMeModal/TurnOffRememberMeModal.tsx @@ -20,8 +20,8 @@ import { logOut } from '../../../actions/user'; import { setAllowLoginWithRememberMe } from '../../../actions/security'; import { useDispatch } from 'react-redux'; import SecureKeychain from '../../../core/SecureKeychain'; -import debounce from 'lodash/debounce'; import { TURN_OFF_REMEMBER_ME_MODAL } from '../../../constants/test-ids'; +import { useNavigation } from '@react-navigation/native'; export const createTurnOffRememberMeModalNavDetails = createNavigationDetails( Routes.MODAL.ROOT_MODAL_FLOW, @@ -30,6 +30,7 @@ export const createTurnOffRememberMeModalNavDetails = createNavigationDetails( const TurnOffRememberMeModal = () => { const { colors, themeAppearance } = useTheme(); + const { navigate } = useNavigation(); const styles = createStyles(colors); const dispatch = useDispatch(); @@ -47,8 +48,7 @@ const TurnOffRememberMeModal = () => { ); const debouncedIsValidPassword = useCallback( - async (text) => - debounce(setDisableButton(!(await isValidPassword(text))), 200), + async (text) => setDisableButton(!(await isValidPassword(text))), [isValidPassword], ); @@ -70,8 +70,9 @@ const TurnOffRememberMeModal = () => { await SecureKeychain.resetGenericPassword(); await KeyringController.setLocked(); dispatch(setAllowLoginWithRememberMe(false)); + navigate(Routes.ONBOARDING.LOGIN); dispatch(logOut()); - }, [dispatch]); + }, [dispatch, navigate]); const disableRememberMe = useCallback(async () => { dismissModal(async () => await turnOffRememberMeAndLockApp()); diff --git a/package.json b/package.json index b44a67d16b3..a635f42db54 100644 --- a/package.json +++ b/package.json @@ -168,7 +168,6 @@ "is-url": "^1.2.4", "json-rpc-engine": "^6.1.0", "json-rpc-middleware-stream": "3.0.0", - "lodash": "^4.17.21", "lottie-react-native": "git+https://github.com/MetaMask/lottie-react-native.git#7ce6a78ac4ac7b9891bc513cb3f12f8b9c9d9106", "metro-config": "^0.71.1", "multihashes": "0.4.14", @@ -279,7 +278,6 @@ "@testing-library/react-hooks": "^8.0.1", "@types/enzyme": "^3.10.9", "@types/jest": "^27.0.1", - "@types/lodash": "^4.14.182", "@types/react": "^17.0.11", "@types/react-native": "^0.64.10", "@types/react-native-material-textfield": "^0.16.5", diff --git a/yarn.lock b/yarn.lock index ccfc30a8d38..0dc1b525af5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3662,11 +3662,6 @@ dependencies: "@types/node" "*" -"@types/lodash@^4.14.182": - version "4.14.182" - resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.182.tgz#05301a4d5e62963227eaafe0ce04dd77c54ea5c2" - integrity sha512-/THyiqyQAP9AfARo4pF+aCGcyiQ94tX/Is2I7HofNRqoYLgN1PBoOWu2/zTA5zMxzP5EFutMtWtGAFRKUe961Q== - "@types/node@*": version "16.0.1" resolved "https://registry.yarnpkg.com/@types/node/-/node-16.0.1.tgz#70cedfda26af7a2ca073fdcc9beb2fff4aa693f8" From 8acf5148f6e4ab30ef137c9942e73de94e8eeca2 Mon Sep 17 00:00:00 2001 From: owencraston Date: Wed, 17 Aug 2022 12:31:36 -0700 Subject: [PATCH 16/17] less padding, no autofocus --- .../TurnOffRememberMeModal/TurnOffRememberMeModal.tsx | 1 - app/components/UI/TurnOffRememberMeModal/styles.ts | 10 ++-------- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/app/components/UI/TurnOffRememberMeModal/TurnOffRememberMeModal.tsx b/app/components/UI/TurnOffRememberMeModal/TurnOffRememberMeModal.tsx index 4d535388d8f..c12c1c16112 100644 --- a/app/components/UI/TurnOffRememberMeModal/TurnOffRememberMeModal.tsx +++ b/app/components/UI/TurnOffRememberMeModal/TurnOffRememberMeModal.tsx @@ -100,7 +100,6 @@ const TurnOffRememberMeModal = () => { StyleSheet.create({ @@ -12,17 +9,14 @@ export const createStyles = (colors: any) => }, areYouSure: { width: '100%', - padding: breakPoint ? 16 : 32, justifyContent: 'center', alignSelf: 'center', + padding: 16, }, textStyle: { - paddingVertical: 12, + paddingVertical: 8, textAlign: 'center', }, - bold: { - ...fontStyles.bold, - }, input: { ...fontStyles.normal, fontSize: 16, From bed990540ab9d2b1e0a78d33f2427179fa9a1af0 Mon Sep 17 00:00:00 2001 From: owencraston Date: Wed, 17 Aug 2022 13:15:38 -0700 Subject: [PATCH 17/17] remove test build --- android/app/build.gradle | 4 ++-- bitrise.yml | 4 ++-- ios/MetaMask.xcodeproj/project.pbxproj | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 1d7841ab24d..f166a3e29b4 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -160,8 +160,8 @@ android { applicationId "io.metamask" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion - versionCode 948 - versionName "5.4.2" + versionCode 939 + versionName "5.5.0" multiDexEnabled true testBuildType System.getProperty('testBuildType', 'debug') missingDimensionStrategy "minReactNative", "minReactNative46" diff --git a/bitrise.yml b/bitrise.yml index 0b462dce393..9ca1343e01b 100644 --- a/bitrise.yml +++ b/bitrise.yml @@ -323,10 +323,10 @@ app: PROJECT_LOCATION_IOS: ios - opts: is_expand: false - VERSION_NAME: 5.4.2 + VERSION_NAME: 5.5.0 - opts: is_expand: false - VERSION_NUMBER: 948 + VERSION_NUMBER: 939 - opts: is_expand: false ANDROID_APK_LINK: '' diff --git a/ios/MetaMask.xcodeproj/project.pbxproj b/ios/MetaMask.xcodeproj/project.pbxproj index 4a29c2e1db5..397bbf51f05 100644 --- a/ios/MetaMask.xcodeproj/project.pbxproj +++ b/ios/MetaMask.xcodeproj/project.pbxproj @@ -825,7 +825,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMaskDebug.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 948; + CURRENT_PROJECT_VERSION = 939; DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = dwarf; DEVELOPMENT_TEAM = 48XVW22RCG; @@ -861,7 +861,7 @@ "\"$(SRCROOT)/MetaMask/System/Library/Frameworks\"", ); LLVM_LTO = YES; - MARKETING_VERSION = 5.4.2; + MARKETING_VERSION = 5.5.0; ONLY_ACTIVE_ARCH = YES; OTHER_CFLAGS = ( "$(inherited)", @@ -892,7 +892,7 @@ CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMask.entitlements; CODE_SIGN_IDENTITY = "iPhone Distribution"; CODE_SIGN_STYLE = Manual; - CURRENT_PROJECT_VERSION = 948; + CURRENT_PROJECT_VERSION = 939; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEVELOPMENT_TEAM = 48XVW22RCG; FRAMEWORK_SEARCH_PATHS = ( @@ -927,7 +927,7 @@ "\"$(SRCROOT)/MetaMask/System/Library/Frameworks\"", ); LLVM_LTO = YES; - MARKETING_VERSION = 5.4.2; + MARKETING_VERSION = 5.5.0; ONLY_ACTIVE_ARCH = NO; OTHER_CFLAGS = ( "$(inherited)",