From 8a15d678c57d09c5889ad495d9acb5d4d05f9c09 Mon Sep 17 00:00:00 2001 From: Cal Leung Date: Wed, 1 Dec 2021 13:57:19 -0800 Subject: [PATCH 1/9] Fix switch navigator replacement logic --- app/components/Nav/App/index.js | 17 ++++++++++------- app/components/UI/DrawerView/index.js | 1 - app/components/Views/LockScreen/index.js | 1 - app/components/Views/Onboarding/index.js | 1 - 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/app/components/Nav/App/index.js b/app/components/Nav/App/index.js index 8d669386de5..ea450ce7213 100644 --- a/app/components/Nav/App/index.js +++ b/app/components/Nav/App/index.js @@ -265,14 +265,17 @@ const App = ({ userLoggedIn }) => { }} > - - - {userLoggedIn && ( + {userLoggedIn ? ( + ) : ( + <> + + + )} diff --git a/app/components/UI/DrawerView/index.js b/app/components/UI/DrawerView/index.js index c4dca96a7b6..6b589b498dd 100644 --- a/app/components/UI/DrawerView/index.js +++ b/app/components/UI/DrawerView/index.js @@ -565,7 +565,6 @@ class DrawerView extends PureComponent { }; logOut = () => { - this.props.navigation.navigate('Login'); this.props.logOut(); }; diff --git a/app/components/Views/LockScreen/index.js b/app/components/Views/LockScreen/index.js index c4b157b8606..f8155117738 100644 --- a/app/components/Views/LockScreen/index.js +++ b/app/components/Views/LockScreen/index.js @@ -96,7 +96,6 @@ class LockScreen extends PureComponent { } logOut = () => { - this.props.navigation.navigate('Login'); this.props.logOut(); }; diff --git a/app/components/Views/Onboarding/index.js b/app/components/Views/Onboarding/index.js index d884acaa0dc..41c1eb17ed2 100644 --- a/app/components/Views/Onboarding/index.js +++ b/app/components/Views/Onboarding/index.js @@ -247,7 +247,6 @@ class Onboarding extends PureComponent { } logOut = () => { - this.props.navigation.navigate('Login'); this.props.logOut(); }; From c0dda4a74bc5fae600a2fd00c19b9baedb17abf7 Mon Sep 17 00:00:00 2001 From: Cal Leung Date: Wed, 1 Dec 2021 14:29:39 -0800 Subject: [PATCH 2/9] Update unit tests --- .../UI/ActionModal/__snapshots__/index.test.tsx.snap | 1 - .../BlockingActionModal/__snapshots__/index.test.tsx.snap | 1 - .../UI/CustomAlert/__snapshots__/index.test.tsx.snap | 1 - .../UI/CustomNonceModal/__snapshots__/index.test.tsx.snap | 1 - .../UI/SelectComponent/__snapshots__/index.test.tsx.snap | 1 - .../Views/BrowserTab/__snapshots__/index.test.tsx.snap | 6 ------ app/core/RPCMethods/wallet_addEthereumChain.test.js | 2 +- 7 files changed, 1 insertion(+), 12 deletions(-) diff --git a/app/components/UI/ActionModal/__snapshots__/index.test.tsx.snap b/app/components/UI/ActionModal/__snapshots__/index.test.tsx.snap index 0712d806cac..5dee7fad5db 100644 --- a/app/components/UI/ActionModal/__snapshots__/index.test.tsx.snap +++ b/app/components/UI/ActionModal/__snapshots__/index.test.tsx.snap @@ -30,7 +30,6 @@ exports[`ActionModal should render correctly 1`] = ` scrollOffset={0} scrollOffsetMax={0} scrollTo={null} - statusBarTranslucent={false} style={ Array [ Object { diff --git a/app/components/UI/BlockingActionModal/__snapshots__/index.test.tsx.snap b/app/components/UI/BlockingActionModal/__snapshots__/index.test.tsx.snap index c2c7a7d9254..d72f4c043ee 100644 --- a/app/components/UI/BlockingActionModal/__snapshots__/index.test.tsx.snap +++ b/app/components/UI/BlockingActionModal/__snapshots__/index.test.tsx.snap @@ -30,7 +30,6 @@ exports[`BlockingActionModal should render correctly 1`] = ` scrollOffset={0} scrollOffsetMax={0} scrollTo={null} - statusBarTranslucent={false} style={ Object { "margin": 0, diff --git a/app/components/UI/CustomAlert/__snapshots__/index.test.tsx.snap b/app/components/UI/CustomAlert/__snapshots__/index.test.tsx.snap index 7bf6b00b6f6..50fee4b882e 100644 --- a/app/components/UI/CustomAlert/__snapshots__/index.test.tsx.snap +++ b/app/components/UI/CustomAlert/__snapshots__/index.test.tsx.snap @@ -30,7 +30,6 @@ exports[`CustomAlert should render correctly 1`] = ` scrollOffset={0} scrollOffsetMax={0} scrollTo={null} - statusBarTranslucent={false} style={ Object { "padding": 20, diff --git a/app/components/UI/CustomNonceModal/__snapshots__/index.test.tsx.snap b/app/components/UI/CustomNonceModal/__snapshots__/index.test.tsx.snap index cf0de621278..de9f4936817 100644 --- a/app/components/UI/CustomNonceModal/__snapshots__/index.test.tsx.snap +++ b/app/components/UI/CustomNonceModal/__snapshots__/index.test.tsx.snap @@ -31,7 +31,6 @@ exports[`CustomNonceModal should render correctly 1`] = ` scrollOffset={0} scrollOffsetMax={0} scrollTo={null} - statusBarTranslucent={false} style={ Object { "justifyContent": "flex-end", diff --git a/app/components/UI/SelectComponent/__snapshots__/index.test.tsx.snap b/app/components/UI/SelectComponent/__snapshots__/index.test.tsx.snap index 08883e02572..e6a2c258350 100644 --- a/app/components/UI/SelectComponent/__snapshots__/index.test.tsx.snap +++ b/app/components/UI/SelectComponent/__snapshots__/index.test.tsx.snap @@ -87,7 +87,6 @@ exports[`SelectComponent should render correctly 1`] = ` scrollOffset={0} scrollOffsetMax={0} scrollTo={null} - statusBarTranslucent={false} style={ Object { "margin": 0, diff --git a/app/components/Views/BrowserTab/__snapshots__/index.test.tsx.snap b/app/components/Views/BrowserTab/__snapshots__/index.test.tsx.snap index 2429d92829b..18d957a6cdd 100644 --- a/app/components/Views/BrowserTab/__snapshots__/index.test.tsx.snap +++ b/app/components/Views/BrowserTab/__snapshots__/index.test.tsx.snap @@ -69,7 +69,6 @@ exports[`Browser should render correctly 1`] = ` scrollOffset={0} scrollOffsetMax={0} scrollTo={null} - statusBarTranslucent={false} style={ Object { "flex": 1, @@ -121,7 +120,6 @@ exports[`Browser should render correctly 1`] = ` scrollOffset={0} scrollOffsetMax={0} scrollTo={null} - statusBarTranslucent={false} style={ Object { "justifyContent": "flex-start", @@ -237,7 +235,6 @@ exports[`Browser should render correctly 1`] = ` scrollOffset={0} scrollOffsetMax={0} scrollTo={null} - statusBarTranslucent={false} style={ Object { "justifyContent": "flex-end", @@ -296,7 +293,6 @@ exports[`Browser should render correctly 1`] = ` scrollOffset={0} scrollOffsetMax={0} scrollTo={null} - statusBarTranslucent={false} style={ Object { "justifyContent": "flex-end", @@ -365,7 +361,6 @@ exports[`Browser should render correctly 1`] = ` scrollOffset={0} scrollOffsetMax={0} scrollTo={null} - statusBarTranslucent={false} style={ Object { "justifyContent": "flex-end", @@ -424,7 +419,6 @@ exports[`Browser should render correctly 1`] = ` scrollOffset={0} scrollOffsetMax={0} scrollTo={null} - statusBarTranslucent={false} style={ Object { "justifyContent": "flex-end", diff --git a/app/core/RPCMethods/wallet_addEthereumChain.test.js b/app/core/RPCMethods/wallet_addEthereumChain.test.js index a669ff7b0ac..98ce8848a3f 100644 --- a/app/core/RPCMethods/wallet_addEthereumChain.test.js +++ b/app/core/RPCMethods/wallet_addEthereumChain.test.js @@ -117,7 +117,7 @@ describe('RPC Method - wallet_addEthereumChain', () => { try { await wallet_addEthereumChain({ req: { - params: [{ ...correctParams, chainId: '0x65' }], + params: [{ ...correctParams, chainId: '0x63' }], }, ...otherOptions, }); From 3c1a7ee9d46afbce72149532e46b5aa633ca8f76 Mon Sep 17 00:00:00 2001 From: Cal Leung Date: Wed, 1 Dec 2021 15:08:31 -0800 Subject: [PATCH 3/9] Fix unit tests. Commit changes from yarn setup --- .../__snapshots__/index.test.tsx.snap | 1 + .../__snapshots__/index.test.tsx.snap | 1 + .../__snapshots__/index.test.tsx.snap | 1 + .../__snapshots__/index.test.tsx.snap | 1 + .../__snapshots__/index.test.tsx.snap | 1 + .../__snapshots__/index.test.tsx.snap | 6 ++++++ ios/Podfile.lock | 20 ++++++++++++------- 7 files changed, 24 insertions(+), 7 deletions(-) diff --git a/app/components/UI/ActionModal/__snapshots__/index.test.tsx.snap b/app/components/UI/ActionModal/__snapshots__/index.test.tsx.snap index 5dee7fad5db..0712d806cac 100644 --- a/app/components/UI/ActionModal/__snapshots__/index.test.tsx.snap +++ b/app/components/UI/ActionModal/__snapshots__/index.test.tsx.snap @@ -30,6 +30,7 @@ exports[`ActionModal should render correctly 1`] = ` scrollOffset={0} scrollOffsetMax={0} scrollTo={null} + statusBarTranslucent={false} style={ Array [ Object { diff --git a/app/components/UI/BlockingActionModal/__snapshots__/index.test.tsx.snap b/app/components/UI/BlockingActionModal/__snapshots__/index.test.tsx.snap index d72f4c043ee..c2c7a7d9254 100644 --- a/app/components/UI/BlockingActionModal/__snapshots__/index.test.tsx.snap +++ b/app/components/UI/BlockingActionModal/__snapshots__/index.test.tsx.snap @@ -30,6 +30,7 @@ exports[`BlockingActionModal should render correctly 1`] = ` scrollOffset={0} scrollOffsetMax={0} scrollTo={null} + statusBarTranslucent={false} style={ Object { "margin": 0, diff --git a/app/components/UI/CustomAlert/__snapshots__/index.test.tsx.snap b/app/components/UI/CustomAlert/__snapshots__/index.test.tsx.snap index 50fee4b882e..7bf6b00b6f6 100644 --- a/app/components/UI/CustomAlert/__snapshots__/index.test.tsx.snap +++ b/app/components/UI/CustomAlert/__snapshots__/index.test.tsx.snap @@ -30,6 +30,7 @@ exports[`CustomAlert should render correctly 1`] = ` scrollOffset={0} scrollOffsetMax={0} scrollTo={null} + statusBarTranslucent={false} style={ Object { "padding": 20, diff --git a/app/components/UI/CustomNonceModal/__snapshots__/index.test.tsx.snap b/app/components/UI/CustomNonceModal/__snapshots__/index.test.tsx.snap index de9f4936817..cf0de621278 100644 --- a/app/components/UI/CustomNonceModal/__snapshots__/index.test.tsx.snap +++ b/app/components/UI/CustomNonceModal/__snapshots__/index.test.tsx.snap @@ -31,6 +31,7 @@ exports[`CustomNonceModal should render correctly 1`] = ` scrollOffset={0} scrollOffsetMax={0} scrollTo={null} + statusBarTranslucent={false} style={ Object { "justifyContent": "flex-end", diff --git a/app/components/UI/SelectComponent/__snapshots__/index.test.tsx.snap b/app/components/UI/SelectComponent/__snapshots__/index.test.tsx.snap index e6a2c258350..08883e02572 100644 --- a/app/components/UI/SelectComponent/__snapshots__/index.test.tsx.snap +++ b/app/components/UI/SelectComponent/__snapshots__/index.test.tsx.snap @@ -87,6 +87,7 @@ exports[`SelectComponent should render correctly 1`] = ` scrollOffset={0} scrollOffsetMax={0} scrollTo={null} + statusBarTranslucent={false} style={ Object { "margin": 0, diff --git a/app/components/Views/BrowserTab/__snapshots__/index.test.tsx.snap b/app/components/Views/BrowserTab/__snapshots__/index.test.tsx.snap index 18d957a6cdd..2429d92829b 100644 --- a/app/components/Views/BrowserTab/__snapshots__/index.test.tsx.snap +++ b/app/components/Views/BrowserTab/__snapshots__/index.test.tsx.snap @@ -69,6 +69,7 @@ exports[`Browser should render correctly 1`] = ` scrollOffset={0} scrollOffsetMax={0} scrollTo={null} + statusBarTranslucent={false} style={ Object { "flex": 1, @@ -120,6 +121,7 @@ exports[`Browser should render correctly 1`] = ` scrollOffset={0} scrollOffsetMax={0} scrollTo={null} + statusBarTranslucent={false} style={ Object { "justifyContent": "flex-start", @@ -235,6 +237,7 @@ exports[`Browser should render correctly 1`] = ` scrollOffset={0} scrollOffsetMax={0} scrollTo={null} + statusBarTranslucent={false} style={ Object { "justifyContent": "flex-end", @@ -293,6 +296,7 @@ exports[`Browser should render correctly 1`] = ` scrollOffset={0} scrollOffsetMax={0} scrollTo={null} + statusBarTranslucent={false} style={ Object { "justifyContent": "flex-end", @@ -361,6 +365,7 @@ exports[`Browser should render correctly 1`] = ` scrollOffset={0} scrollOffsetMax={0} scrollTo={null} + statusBarTranslucent={false} style={ Object { "justifyContent": "flex-end", @@ -419,6 +424,7 @@ exports[`Browser should render correctly 1`] = ` scrollOffset={0} scrollOffsetMax={0} scrollTo={null} + statusBarTranslucent={false} style={ Object { "justifyContent": "flex-end", diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 98e58002f69..d3b173e2be9 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -1,6 +1,8 @@ PODS: - boost-for-react-native (1.63.0) - Branch (1.39.2) + - BVLinearGradient (2.5.6): + - React - CocoaAsyncSocket (7.6.5) - DoubleConversion (1.1.6) - FBLazyVector (0.63.4) @@ -375,8 +377,8 @@ PODS: - React - RNCClipboard (1.8.4): - React-Core - - RNCMaskedView (0.1.11): - - React + - RNCMaskedView (0.2.6): + - React-Core - RNCPicker (1.8.1): - React-Core - RNDefaultPreference (1.4.3): @@ -420,6 +422,7 @@ PODS: - Yoga (~> 1.14) DEPENDENCIES: + - BVLinearGradient (from `../node_modules/react-native-linear-gradient`) - DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`) - FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector`) - FBReactNativeSpec (from `../node_modules/react-native/Libraries/FBReactNativeSpec`) @@ -488,7 +491,7 @@ DEPENDENCIES: - "RNCAsyncStorage (from `../node_modules/@react-native-community/async-storage`)" - "RNCCheckbox (from `../node_modules/@react-native-community/checkbox`)" - "RNCClipboard (from `../node_modules/@react-native-clipboard/clipboard`)" - - "RNCMaskedView (from `../node_modules/@react-native-community/masked-view`)" + - "RNCMaskedView (from `../node_modules/@react-native-masked-view/masked-view`)" - "RNCPicker (from `../node_modules/@react-native-community/picker`)" - RNDefaultPreference (from `../node_modules/react-native-default-preference`) - RNDeviceInfo (from `../node_modules/react-native-device-info`) @@ -526,6 +529,8 @@ SPEC REPOS: - YogaKit EXTERNAL SOURCES: + BVLinearGradient: + :path: "../node_modules/react-native-linear-gradient" DoubleConversion: :podspec: "../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec" FBLazyVector: @@ -621,7 +626,7 @@ EXTERNAL SOURCES: RNCClipboard: :path: "../node_modules/@react-native-clipboard/clipboard" RNCMaskedView: - :path: "../node_modules/@react-native-community/masked-view" + :path: "../node_modules/@react-native-masked-view/masked-view" RNCPicker: :path: "../node_modules/@react-native-community/picker" RNDefaultPreference: @@ -660,8 +665,9 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c Branch: 6a281514287f99d707615ac62c2cca69e0213df0 + BVLinearGradient: e3aad03778a456d77928f594a649e96995f1c872 CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99 - DoubleConversion: cde416483dac037923206447da6e1454df403714 + DoubleConversion: 831926d9b8bf8166fd87886c4abab286c2422662 FBLazyVector: 3bb422f41b18121b71783a905c10e58606f7dc3e FBReactNativeSpec: f2c97f2529dd79c083355182cc158c9f98f4bd6e Flipper: 1bd2db48dcc31e4b167b9a33ec1df01c2ded4893 @@ -672,7 +678,7 @@ SPEC CHECKSUMS: Flipper-RSocket: 127954abe8b162fcaf68d2134d34dc2bd7076154 FlipperKit: 651f50a42eb95c01b3e89a60996dd6aded529eeb Folly: b73c3869541e86821df3c387eb0af5f65addfab4 - glog: 40a13f7840415b9a77023fbcae0f1e6f43192af3 + glog: 5337263514dd6f09803962437687240c5dc39aa4 libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913 lottie-ios: a50d5c0160425cd4b01b852bb9578963e6d92d31 lottie-react-native: 7ca15c46249b61e3f9ffcf114cb4123e907a2156 @@ -718,7 +724,7 @@ SPEC CHECKSUMS: RNCAsyncStorage: b03032fdbdb725bea0bd9e5ec5a7272865ae7398 RNCCheckbox: 357578d3b42652c78ee9a1bb9bcfc3195af6e161 RNCClipboard: ddd4d291537f1667209c9c405aaa4307297e252e - RNCMaskedView: 0e1bc4bfa8365eba5fbbb71e07fbdc0555249489 + RNCMaskedView: c298b644a10c0c142055b3ae24d83879ecb13ccd RNCPicker: 914b557e20b3b8317b084aca9ff4b4edb95f61e4 RNDefaultPreference: 2f8d6d54230edbd78708ada8d63bb275e5a8415b RNDeviceInfo: 8d3a29207835f972bce883723882980143270d55 From 3d3b529b372b44d77ff6df624f81e7bc4150460f Mon Sep 17 00:00:00 2001 From: Cal Leung Date: Thu, 2 Dec 2021 14:56:40 -0800 Subject: [PATCH 4/9] Fix login bug. Temporarily control splash animation. --- app/actions/user/index.js | 6 ++ app/components/Nav/App/index.js | 97 ++++++++++++------- app/components/UI/DrawerView/index.js | 1 + app/components/UI/MetaMaskAnimation/index.tsx | 2 +- app/components/Views/LockScreen/index.js | 1 + app/components/Views/Login/index.js | 11 ++- app/components/Views/Onboarding/index.js | 1 + app/reducers/user/index.js | 6 ++ app/store/index.js | 12 ++- 9 files changed, 96 insertions(+), 41 deletions(-) diff --git a/app/actions/user/index.js b/app/actions/user/index.js index 737dd76e71a..95c7cc29afc 100644 --- a/app/actions/user/index.js +++ b/app/actions/user/index.js @@ -76,3 +76,9 @@ export function logOut() { type: 'LOGOUT', }; } + +export function checkedAuth() { + return { + type: 'CHECKED_AUTH', + }; +} diff --git a/app/components/Nav/App/index.js b/app/components/Nav/App/index.js index ea450ce7213..c271c6da1b4 100644 --- a/app/components/Nav/App/index.js +++ b/app/components/Nav/App/index.js @@ -1,6 +1,6 @@ import React, { useCallback, useEffect, useRef, useState } from 'react'; import { NavigationContainer, CommonActions } from '@react-navigation/native'; -import { Animated } from 'react-native'; +import { Animated, StyleSheet, View } from 'react-native'; import { createStackNavigator } from '@react-navigation/stack'; import { createDrawerNavigator } from '@react-navigation/drawer'; import Login from '../../Views/Login'; @@ -30,10 +30,14 @@ import { trackErrorAsAnalytics } from '../../../util/analyticsV2'; import { routingInstrumentation } from '../../../util/setupSentry'; import Analytics from '../../../core/Analytics'; import AsyncStorage from '@react-native-community/async-storage'; -import { connect } from 'react-redux'; - +import { connect, useSelector, useDispatch } from 'react-redux'; import { EXISTING_USER, CURRENT_APP_VERSION, LAST_APP_VERSION } from '../../../constants/storage'; import { getVersion } from 'react-native-device-info'; +import { checkedAuth } from '../../../actions/user'; + +const styles = StyleSheet.create({ + fill: { flex: 1 }, +}); const Stack = createStackNavigator(); const Drawer = createDrawerNavigator(); @@ -147,6 +151,10 @@ const App = ({ userLoggedIn }) => { const [route, setRoute] = useState(); const [animationPlayed, setAnimationPlayed] = useState(); + const isAuthChecked = useSelector((state) => state.user.isAuthChecked); + const dispatch = useDispatch(); + const triggerCheckedAuth = () => dispatch(checkedAuth()); + const handleDeeplink = useCallback(({ error, params, uri }) => { if (error) { trackErrorAsAnalytics(error, 'Branch:'); @@ -196,6 +204,9 @@ const App = ({ userLoggedIn }) => { const existingUser = await AsyncStorage.getItem(EXISTING_USER); const route = !existingUser ? 'OnboardingRootNav' : 'Login'; setRoute(route); + if (!existingUser) { + triggerCheckedAuth(); + } } checkExsiting(); @@ -225,14 +236,23 @@ const App = ({ userLoggedIn }) => { } catch (error) { Logger.error(error); } - - animation?.current?.play(); - animationName?.current?.play(); } startApp(); }, []); + useEffect(() => { + if (!isAuthChecked) { + return; + } + const startAnimation = async () => { + await new Promise((res) => setTimeout(res, 50)); + animation?.current?.play(); + animationName?.current?.play(); + }; + startAnimation(); + }, [isAuthChecked]); + const onAnimationFinished = useCallback(() => { Animated.timing(opacity, { toValue: 0, @@ -244,41 +264,44 @@ const App = ({ userLoggedIn }) => { }); }, [opacity]); - if (!animationPlayed) { - return ( - - ); - } + const renderSplash = () => { + if (!animationPlayed) { + return ( + + ); + } + return null; + }; return ( // do not render unless a route is defined (route && ( - { - routingInstrumentation.registerNavigationContainer(navigator); - }} - > - - {userLoggedIn ? ( - - ) : ( - <> - - - - )} - - + + { + routingInstrumentation.registerNavigationContainer(navigator); + }} + > + + + + {userLoggedIn && ( + + )} + + + {renderSplash()} + )) || null ); diff --git a/app/components/UI/DrawerView/index.js b/app/components/UI/DrawerView/index.js index 6b589b498dd..c4dca96a7b6 100644 --- a/app/components/UI/DrawerView/index.js +++ b/app/components/UI/DrawerView/index.js @@ -565,6 +565,7 @@ class DrawerView extends PureComponent { }; logOut = () => { + this.props.navigation.navigate('Login'); this.props.logOut(); }; diff --git a/app/components/UI/MetaMaskAnimation/index.tsx b/app/components/UI/MetaMaskAnimation/index.tsx index a68730f9ea2..f0fed6606d9 100644 --- a/app/components/UI/MetaMaskAnimation/index.tsx +++ b/app/components/UI/MetaMaskAnimation/index.tsx @@ -9,7 +9,7 @@ const LOGO_PADDING = 25; const styles = StyleSheet.create({ main: { - flex: 1, + ...StyleSheet.absoluteFillObject, backgroundColor: colors.white, }, metamaskName: { diff --git a/app/components/Views/LockScreen/index.js b/app/components/Views/LockScreen/index.js index f8155117738..c4b157b8606 100644 --- a/app/components/Views/LockScreen/index.js +++ b/app/components/Views/LockScreen/index.js @@ -96,6 +96,7 @@ class LockScreen extends PureComponent { } logOut = () => { + this.props.navigation.navigate('Login'); this.props.logOut(); }; diff --git a/app/components/Views/Login/index.js b/app/components/Views/Login/index.js index 56118fdeff5..b1307e7f9e2 100644 --- a/app/components/Views/Login/index.js +++ b/app/components/Views/Login/index.js @@ -25,7 +25,7 @@ import { strings } from '../../../../locales/i18n'; import SecureKeychain from '../../../core/SecureKeychain'; import FadeOutOverlay from '../../UI/FadeOutOverlay'; import setOnboardingWizardStep from '../../../actions/wizard'; -import { logIn, logOut } from '../../../actions/user'; +import { logIn, logOut, checkedAuth } from '../../../actions/user'; import { connect } from 'react-redux'; import Device from '../../../util/device'; import { OutlinedTextField } from 'react-native-material-textfield'; @@ -214,6 +214,10 @@ class Login extends PureComponent { selectedAddress: PropTypes.string, logIn: PropTypes.func, logOut: PropTypes.func, + /** + * TEMPORARY state for animation control on Nav/App/index.js + */ + checkedAuth: PropTypes.func, }; state = { @@ -273,9 +277,11 @@ class Login extends PureComponent { console.warn(e); } } else { - this.checkIfRememberMeEnabled(); + await this.checkIfRememberMeEnabled(); } } + + this.props.checkedAuth(); } componentWillUnmount() { @@ -653,6 +659,7 @@ const mapDispatchToProps = (dispatch) => ({ setOnboardingWizardStep: (step) => dispatch(setOnboardingWizardStep(step)), logIn: () => dispatch(logIn()), logOut: () => dispatch(logOut()), + checkedAuth: () => dispatch(checkedAuth()), }); export default connect(mapStateToProps, mapDispatchToProps)(Login); diff --git a/app/components/Views/Onboarding/index.js b/app/components/Views/Onboarding/index.js index 41c1eb17ed2..d884acaa0dc 100644 --- a/app/components/Views/Onboarding/index.js +++ b/app/components/Views/Onboarding/index.js @@ -247,6 +247,7 @@ class Onboarding extends PureComponent { } logOut = () => { + this.props.navigation.navigate('Login'); this.props.logOut(); }; diff --git a/app/reducers/user/index.js b/app/reducers/user/index.js index 698f73dbb1d..f4369581a7d 100644 --- a/app/reducers/user/index.js +++ b/app/reducers/user/index.js @@ -7,10 +7,16 @@ const initialState = { protectWalletModalVisible: false, gasEducationCarouselSeen: false, userLoggedIn: false, + isAuthChecked: false, }; const userReducer = (state = initialState, action) => { switch (action.type) { + case 'CHECKED_AUTH': + return { + ...state, + isAuthChecked: true, + }; case 'LOGIN': return { ...state, diff --git a/app/store/index.js b/app/store/index.js index 52466cf71c5..d1ca9267476 100644 --- a/app/store/index.js +++ b/app/store/index.js @@ -85,12 +85,22 @@ const persistTransform = createTransform( { whitelist: ['engine'] } ); +const persistUserTransform = createTransform( + (inboundState) => { + const { isAuthChecked, ...state } = inboundState; + // Reconstruct data to persist + return state; + }, + null, + { whitelist: ['user'] } +); + const persistConfig = { key: 'root', version, blacklist: ['onboarding'], storage: MigratedStorage, - transforms: [persistTransform], + transforms: [persistTransform, persistUserTransform], stateReconciler: autoMergeLevel2, // see "Merge Process" section for details. migrate: createMigrate(migrations, { debug: false }), timeout: TIMEOUT, From a55b64e6a96d14c1194d147af6389335e9c4d58c Mon Sep 17 00:00:00 2001 From: Curtis Date: Fri, 3 Dec 2021 18:34:18 -0500 Subject: [PATCH 5/9] Fix login bug --- app/components/Views/Login/index.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/components/Views/Login/index.js b/app/components/Views/Login/index.js index b1307e7f9e2..fe2911d70bf 100644 --- a/app/components/Views/Login/index.js +++ b/app/components/Views/Login/index.js @@ -276,6 +276,9 @@ class Login extends PureComponent { } catch (e) { console.warn(e); } + if (!enabled) { + await this.checkIfRememberMeEnabled(); + } } else { await this.checkIfRememberMeEnabled(); } @@ -299,7 +302,6 @@ class Login extends PureComponent { */ checkIfRememberMeEnabled = async () => { const credentials = await SecureKeychain.getGenericPassword(); - //This if (credentials) { this.setState({ rememberMe: true }); // Restore vault with existing credentials @@ -446,6 +448,8 @@ class Login extends PureComponent { updateBiometryChoice = async (biometryChoice) => { if (!biometryChoice) { await AsyncStorage.setItem(BIOMETRY_CHOICE_DISABLED, TRUE); + // This line will disable biometrics the next time SecureKeychain.getGenericPassword is called + await SecureKeychain.resetGenericPassword(); } else { await AsyncStorage.removeItem(BIOMETRY_CHOICE_DISABLED); } From 646edf4fb776922f103ade121b62c9b8f9d99624 Mon Sep 17 00:00:00 2001 From: Cal Leung Date: Tue, 7 Dec 2021 14:58:01 -0800 Subject: [PATCH 6/9] Wait for login event --- app/components/Views/Login/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/components/Views/Login/index.js b/app/components/Views/Login/index.js index f241c8b8f25..7d605715317 100644 --- a/app/components/Views/Login/index.js +++ b/app/components/Views/Login/index.js @@ -506,7 +506,7 @@ class Login extends PureComponent { this.setState({ password: credentials.password }); field.setValue(credentials.password); field.blur(); - this.onLogin(true); + await this.onLogin(true); } catch (error) { Logger.log(error); } From 867f007bc111146cea3b639e18c1fd7e2f3ff987 Mon Sep 17 00:00:00 2001 From: Cal Leung Date: Tue, 7 Dec 2021 20:13:57 -0800 Subject: [PATCH 7/9] Properly handle biometrics button. Conditionally handle initial auth logic on Login screen. --- app/actions/user/index.js | 11 +++- app/components/Nav/App/index.js | 2 +- app/components/UI/DrawerView/index.js | 2 + app/components/Views/Login/index.js | 76 +++++++++++++++------------ app/reducers/user/index.js | 2 + app/store/index.js | 2 +- ios/Podfile.lock | 4 +- 7 files changed, 59 insertions(+), 40 deletions(-) diff --git a/app/actions/user/index.js b/app/actions/user/index.js index 95c7cc29afc..c370d110835 100644 --- a/app/actions/user/index.js +++ b/app/actions/user/index.js @@ -77,8 +77,17 @@ export function logOut() { }; } -export function checkedAuth() { +/** + * Temporary action to control auth flow + * + * @param {string} initialScreen - "login" or "onboarding" + * @returns - void + */ +export function checkedAuth(initialScreen) { return { type: 'CHECKED_AUTH', + payload: { + initialScreen, + }, }; } diff --git a/app/components/Nav/App/index.js b/app/components/Nav/App/index.js index 7a6d4101b84..b92c60b961c 100644 --- a/app/components/Nav/App/index.js +++ b/app/components/Nav/App/index.js @@ -153,7 +153,7 @@ const App = ({ userLoggedIn }) => { const isAuthChecked = useSelector((state) => state.user.isAuthChecked); const dispatch = useDispatch(); - const triggerCheckedAuth = () => dispatch(checkedAuth()); + const triggerCheckedAuth = () => dispatch(checkedAuth('onboarding')); const handleDeeplink = useCallback(({ error, params, uri }) => { if (error) { diff --git a/app/components/UI/DrawerView/index.js b/app/components/UI/DrawerView/index.js index ae498554f55..35d0d7b74bb 100644 --- a/app/components/UI/DrawerView/index.js +++ b/app/components/UI/DrawerView/index.js @@ -16,6 +16,7 @@ import { renderFromWei, renderFiat } from '../../../util/number'; import { strings } from '../../../../locales/i18n'; import { DrawerActions } from '@react-navigation/native'; import Modal from 'react-native-modal'; +import SecureKeychain from '../../../core/SecureKeychain'; import { toggleNetworkModal, toggleAccountsModal, toggleReceiveModal } from '../../../actions/modals'; import { showAlert } from '../../../actions/alert'; import { getEtherscanAddressUrl, getEtherscanBaseUrl } from '../../../util/etherscan'; @@ -572,6 +573,7 @@ class DrawerView extends PureComponent { onPress = async () => { const { passwordSet } = this.props; const { KeyringController } = Engine.context; + await SecureKeychain.resetGenericPassword(); await KeyringController.setLocked(); if (!passwordSet) { this.props.navigation.navigate('OnboardingRootNav', { diff --git a/app/components/Views/Login/index.js b/app/components/Views/Login/index.js index 7d605715317..4a4e2854444 100644 --- a/app/components/Views/Login/index.js +++ b/app/components/Views/Login/index.js @@ -205,9 +205,9 @@ class Login extends PureComponent { */ setOnboardingWizardStep: PropTypes.func, /** - * Boolean flag that determines if password has been set + * Temporary string that controls if componentDidMount should handle initial auth logic on mount */ - passwordSet: PropTypes.bool, + initialScreen: PropTypes.string, /** * A string representing the selected address => account */ @@ -239,39 +239,33 @@ class Login extends PureComponent { fieldRef = React.createRef(); async componentDidMount() { + const { initialScreen } = this.props; const { KeyringController } = Engine.context; + const shouldHandleInitialAuth = initialScreen !== 'onboarding'; BackHandler.addEventListener('hardwareBackPress', this.handleBackPress); + // Lock keyring just in case if (KeyringController.isUnlocked()) { await KeyringController.setLocked(); } - if (!this.props.passwordSet) { - try { - await KeyringController.submitPassword(''); - await SecureKeychain.resetGenericPassword(); - this.props.navigation.navigate('HomeNav'); - } catch (e) { - // + const biometryType = await SecureKeychain.getSupportedBiometryType(); + if (biometryType) { + let enabled = true; + const previouslyDisabled = await AsyncStorage.getItem(BIOMETRY_CHOICE_DISABLED); + if (previouslyDisabled && previouslyDisabled === TRUE) { + enabled = false; } - } else { - const biometryType = await SecureKeychain.getSupportedBiometryType(); - if (biometryType) { - let enabled = true; - const previouslyDisabled = await AsyncStorage.getItem(BIOMETRY_CHOICE_DISABLED); - if (previouslyDisabled && previouslyDisabled === TRUE) { - enabled = false; - } - this.setState({ - biometryType: Device.isAndroid() ? 'biometrics' : biometryType, - biometryChoice: enabled, - biometryPreviouslyDisabled: !!previouslyDisabled, - }); + this.setState({ + biometryType: Device.isAndroid() ? 'biometrics' : biometryType, + biometryChoice: enabled, + biometryPreviouslyDisabled: !!previouslyDisabled, + }); + if (shouldHandleInitialAuth) { try { if (enabled && !previouslyDisabled) { - const hasBiometricCredentials = await this.tryBiometric(); - this.setState({ hasBiometricCredentials }); + await this.tryBiometric(); } } catch (e) { console.warn(e); @@ -279,9 +273,9 @@ class Login extends PureComponent { if (!enabled) { await this.checkIfRememberMeEnabled(); } - } else { - await this.checkIfRememberMeEnabled(); } + } else { + shouldHandleInitialAuth && (await this.checkIfRememberMeEnabled()); } this.props.checkedAuth(); @@ -318,6 +312,8 @@ class Login extends PureComponent { this.props.setOnboardingWizardStep(1); } + // Only way to land back on Login is to log out, which clears credentials (meaning we should not show biometric button) + this.setState({ hasBiometricCredentials: false }); delete credentials.password; this.props.logIn(); this.props.navigation.navigate('HomeNav'); @@ -362,7 +358,8 @@ class Login extends PureComponent { this.props.setOnboardingWizardStep(1); this.props.navigation.navigate('HomeNav'); } - this.setState({ loading: false, password: '' }); + // Only way to land back on Login is to log out, which clears credentials (meaning we should not show biometric button) + this.setState({ loading: false, password: '', hasBiometricCredentials: false }); field.setValue(''); } catch (e) { // Should we force people to enable passcode / biometrics? @@ -394,6 +391,10 @@ class Login extends PureComponent { } }; + triggerLogIn = () => { + this.onLogin(); + }; + delete = async () => { const { KeyringController } = Engine.context; try { @@ -448,8 +449,6 @@ class Login extends PureComponent { updateBiometryChoice = async (biometryChoice) => { if (!biometryChoice) { await AsyncStorage.setItem(BIOMETRY_CHOICE_DISABLED, TRUE); - // This line will disable biometrics the next time SecureKeychain.getGenericPassword is called - await SecureKeychain.resetGenericPassword(); } else { await AsyncStorage.removeItem(BIOMETRY_CHOICE_DISABLED); } @@ -501,17 +500,24 @@ class Login extends PureComponent { field.blur(); try { const credentials = await SecureKeychain.getGenericPassword(); - if (!credentials) return false; + if (!credentials) { + this.setState({ hasBiometricCredentials: false }); + return; + } field.blur(); this.setState({ password: credentials.password }); field.setValue(credentials.password); field.blur(); await this.onLogin(true); } catch (error) { + const errObj = new Error(error); + const canceledBiometrics = errObj.message === 'Error: User canceled the operation.'; + if (canceledBiometrics) { + this.setState({ hasBiometricCredentials: true }); + } Logger.log(error); } field.blur(); - return true; }; render = () => ( @@ -601,7 +607,7 @@ class Login extends PureComponent { value={this.state.password} baseColor={colors.grey500} tintColor={colors.blue} - onSubmitEditing={this.onLogin} + onSubmitEditing={this.triggerLogIn} renderRightAccessory={() => ( - + {this.state.loading ? ( ) : ( @@ -655,15 +661,15 @@ class Login extends PureComponent { } const mapStateToProps = (state) => ({ - passwordSet: state.user.passwordSet, selectedAddress: state.engine.backgroundState.PreferencesController?.selectedAddress, + initialScreen: state.user.initialScreen, }); const mapDispatchToProps = (dispatch) => ({ setOnboardingWizardStep: (step) => dispatch(setOnboardingWizardStep(step)), logIn: () => dispatch(logIn()), logOut: () => dispatch(logOut()), - checkedAuth: () => dispatch(checkedAuth()), + checkedAuth: () => dispatch(checkedAuth('login')), }); export default connect(mapStateToProps, mapDispatchToProps)(Login); diff --git a/app/reducers/user/index.js b/app/reducers/user/index.js index f4369581a7d..3faf7f86c2a 100644 --- a/app/reducers/user/index.js +++ b/app/reducers/user/index.js @@ -8,6 +8,7 @@ const initialState = { gasEducationCarouselSeen: false, userLoggedIn: false, isAuthChecked: false, + initialScreen: '', }; const userReducer = (state = initialState, action) => { @@ -16,6 +17,7 @@ const userReducer = (state = initialState, action) => { return { ...state, isAuthChecked: true, + initialScreen: action.payload.initialScreen, }; case 'LOGIN': return { diff --git a/app/store/index.js b/app/store/index.js index d1ca9267476..47c62c669f9 100644 --- a/app/store/index.js +++ b/app/store/index.js @@ -87,7 +87,7 @@ const persistTransform = createTransform( const persistUserTransform = createTransform( (inboundState) => { - const { isAuthChecked, ...state } = inboundState; + const { initialScreen, isAuthChecked, ...state } = inboundState; // Reconstruct data to persist return state; }, diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 4171fa0011e..d0cf51d0310 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -672,7 +672,7 @@ SPEC CHECKSUMS: Branch: 6a281514287f99d707615ac62c2cca69e0213df0 BVLinearGradient: e3aad03778a456d77928f594a649e96995f1c872 CocoaAsyncSocket: 065fd1e645c7abab64f7a6a2007a48038fdc6a99 - DoubleConversion: cde416483dac037923206447da6e1454df403714 + DoubleConversion: 831926d9b8bf8166fd87886c4abab286c2422662 FBLazyVector: 3bb422f41b18121b71783a905c10e58606f7dc3e FBReactNativeSpec: f2c97f2529dd79c083355182cc158c9f98f4bd6e Flipper: 1bd2db48dcc31e4b167b9a33ec1df01c2ded4893 @@ -683,7 +683,7 @@ SPEC CHECKSUMS: Flipper-RSocket: 127954abe8b162fcaf68d2134d34dc2bd7076154 FlipperKit: 651f50a42eb95c01b3e89a60996dd6aded529eeb Folly: b73c3869541e86821df3c387eb0af5f65addfab4 - glog: 40a13f7840415b9a77023fbcae0f1e6f43192af3 + glog: 5337263514dd6f09803962437687240c5dc39aa4 libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913 lottie-ios: a50d5c0160425cd4b01b852bb9578963e6d92d31 lottie-react-native: 7ca15c46249b61e3f9ffcf114cb4123e907a2156 From f6326691aa76f313ac726b24e86ad53e6101a846 Mon Sep 17 00:00:00 2001 From: Cal Leung Date: Wed, 8 Dec 2021 13:14:35 -0800 Subject: [PATCH 8/9] Clean up biometrics logic --- app/components/Views/Login/index.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/app/components/Views/Login/index.js b/app/components/Views/Login/index.js index 4a4e2854444..0f0d060eabc 100644 --- a/app/components/Views/Login/index.js +++ b/app/components/Views/Login/index.js @@ -251,11 +251,8 @@ class Login extends PureComponent { const biometryType = await SecureKeychain.getSupportedBiometryType(); if (biometryType) { - let enabled = true; const previouslyDisabled = await AsyncStorage.getItem(BIOMETRY_CHOICE_DISABLED); - if (previouslyDisabled && previouslyDisabled === TRUE) { - enabled = false; - } + const enabled = !(previouslyDisabled && previouslyDisabled === TRUE); this.setState({ biometryType: Device.isAndroid() ? 'biometrics' : biometryType, From f6a067b6cf823ca01717d1bcbe7213898b61d220 Mon Sep 17 00:00:00 2001 From: Cal Leung Date: Wed, 8 Dec 2021 15:12:46 -0800 Subject: [PATCH 9/9] Catch all canceled biometric events --- app/components/Views/Login/index.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/app/components/Views/Login/index.js b/app/components/Views/Login/index.js index 0f0d060eabc..b695790cfe6 100644 --- a/app/components/Views/Login/index.js +++ b/app/components/Views/Login/index.js @@ -507,11 +507,7 @@ class Login extends PureComponent { field.blur(); await this.onLogin(true); } catch (error) { - const errObj = new Error(error); - const canceledBiometrics = errObj.message === 'Error: User canceled the operation.'; - if (canceledBiometrics) { - this.setState({ hasBiometricCredentials: true }); - } + this.setState({ hasBiometricCredentials: true }); Logger.log(error); } field.blur();