Skip to content

Commit

Permalink
TW-346: Fix unlock after minimize (#731)
Browse files Browse the repository at this point in the history
Co-authored-by: Andrii Ivaniv <[email protected]>
  • Loading branch information
alex-tsx and unixvb authored Jan 30, 2023
1 parent 5a4b82c commit c33d784
Show file tree
Hide file tree
Showing 11 changed files with 84 additions and 44 deletions.
9 changes: 9 additions & 0 deletions .editorconfig copy
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Editor configuration, see http://editorconfig.org
root = true

[*]
charset = utf-8
indent_style = space
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true
1 change: 1 addition & 0 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,7 @@ dependencies {

//noinspection GradleDynamicVersion
implementation "com.facebook.react:react-native:+" // From node_modules
implementation project(':react-native-keychain')

implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0"
implementation "androidx.core:core-splashscreen:1.0.0"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
import com.facebook.react.ReactPackage;
import com.facebook.react.config.ReactFeatureFlags;
import com.facebook.soloader.SoLoader;
import com.oblador.keychain.KeychainPackage;
import com.oblador.keychain.KeychainModuleBuilder;
import com.templewallet.newarchitecture.MainApplicationReactNativeHost;
import java.lang.reflect.InvocationTargetException;
import java.util.List;
Expand All @@ -28,6 +30,11 @@ public boolean getUseDeveloperSupport() {
protected List<ReactPackage> getPackages() {
@SuppressWarnings("UnnecessaryLocalVariable")
List<ReactPackage> packages = new PackageList(this).getPackages();
packages.add(
new KeychainPackage(
new KeychainModuleBuilder().withoutWarmUp()
)
);
// Packages that cannot be autolinked yet can be added manually here, for example:
// packages.add(new MyReactNativePackage());
return packages;
Expand Down
4 changes: 4 additions & 0 deletions android/settings.gradle
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
rootProject.name = 'TempleWallet'
apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings)
include ':app'

include ':react-native-keychain'
project(':react-native-keychain').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-keychain/android')

includeBuild('../node_modules/react-native-gradle-plugin')

if (settings.hasProperty("newArchEnabled") && settings.newArchEnabled == "true") {
Expand Down
9 changes: 8 additions & 1 deletion react-native.config.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
module.exports = {
assets: ['./src/assets/fonts/']
assets: ['./src/assets/fonts/'],
dependencies: {
'react-native-keychain': {
platforms: {
android: null
}
}
}
};
48 changes: 22 additions & 26 deletions src/app/app.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
import { AnalyticsProvider } from '@segment/analytics-react-native';
import React from 'react';
import { LogBox } from 'react-native';
import { hide } from 'react-native-bootsplash';
import { GestureHandlerRootView } from 'react-native-gesture-handler';
import { SafeAreaProvider } from 'react-native-safe-area-context';
import { enableScreens } from 'react-native-screens';
import { Provider } from 'react-redux';
import { PersistGate } from 'redux-persist/integration/react';

import { BiometryAvailabilityProvider } from '../biometry/biometry-availability.provider';
import { HIDE_SPLASH_SCREEN_TIMEOUT } from '../config/animation';
import { HideBalanceProvider } from '../hooks/hide-balance/hide-balance.provider';
import { useDelayedEffect } from '../hooks/use-delayed-effect.hook';
import { HideBootsplashProvider } from '../hooks/use-hide-bootsplash';
import { RootStackScreen } from '../navigator/root-stack';
import { AppLockContextProvider } from '../shelter/app-lock/app-lock';
import { persistor, store } from '../store/store';
Expand All @@ -24,27 +22,25 @@ initSentry();
enableScreens();
LogBox.ignoreAllLogs();

export const App = () => {
useDelayedEffect(HIDE_SPLASH_SCREEN_TIMEOUT, () => void hide({ fade: true }), []);

return (
<GestureHandlerRootView style={AppStyles.root}>
<AnalyticsProvider client={segmentClient}>
<Provider store={store}>
<PersistGate persistor={persistor} loading={null}>
<BiometryAvailabilityProvider>
<HideBalanceProvider>
<AppLockContextProvider>
<SafeAreaProvider>
export const App = () => (
<GestureHandlerRootView style={AppStyles.root}>
<AnalyticsProvider client={segmentClient}>
<Provider store={store}>
<PersistGate persistor={persistor} loading={null}>
<BiometryAvailabilityProvider>
<HideBalanceProvider>
<AppLockContextProvider>
<SafeAreaProvider>
<HideBootsplashProvider>
<RootStackScreen />
<ToastProvider />
</SafeAreaProvider>
</AppLockContextProvider>
</HideBalanceProvider>
</BiometryAvailabilityProvider>
</PersistGate>
</Provider>
</AnalyticsProvider>
</GestureHandlerRootView>
);
};
</HideBootsplashProvider>
<ToastProvider />
</SafeAreaProvider>
</AppLockContextProvider>
</HideBalanceProvider>
</BiometryAvailabilityProvider>
</PersistGate>
</Provider>
</AnalyticsProvider>
</GestureHandlerRootView>
);
9 changes: 0 additions & 9 deletions src/hooks/use-delayed-effect.hook.ts

This file was deleted.

23 changes: 23 additions & 0 deletions src/hooks/use-hide-bootsplash.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import React, { createContext, FC, useContext, useEffect, useState } from 'react';
import { hide } from 'react-native-bootsplash';

import { HIDE_SPLASH_SCREEN_TIMEOUT } from '../config/animation';

const context = createContext(true);

const Provider = context.Provider;

export const HideBootsplashProvider: FC = ({ children }) => {
const [atBootsplash, setAtBootsplash] = useState(true);

useEffect(() => {
(async () => {
await hide({ fade: true });
setTimeout(() => void setAtBootsplash(false), HIDE_SPLASH_SCREEN_TIMEOUT);
})();
}, []);

return <Provider value={atBootsplash}>{children}</Provider>;
};

export const useAtBootsplash = () => useContext(context);
14 changes: 8 additions & 6 deletions src/screens/enter-password/enter-password.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Formik } from 'formik';
import React from 'react';
import React, { useEffect } from 'react';
import { Text, View } from 'react-native';

import { useBiometryAvailability } from '../../biometry/use-biometry-availability.hook';
Expand All @@ -13,10 +13,9 @@ import { InsetSubstitute } from '../../components/inset-substitute/inset-substit
import { Label } from '../../components/label/label';
import { Quote } from '../../components/quote/quote';
import { ScreenContainer } from '../../components/screen-container/screen-container';
import { HIDE_SPLASH_SCREEN_TIMEOUT } from '../../config/animation';
import { MAX_PASSWORD_ATTEMPTS } from '../../config/security';
import { FormPasswordInput } from '../../form/form-password-input';
import { useDelayedEffect } from '../../hooks/use-delayed-effect.hook';
import { useAtBootsplash } from '../../hooks/use-hide-bootsplash';
import { usePasswordLock } from '../../hooks/use-password-lock.hook';
import { useResetDataHandler } from '../../hooks/use-reset-data-handler.hook';
import { OverlayEnum } from '../../navigator/enums/overlay.enum';
Expand All @@ -36,6 +35,8 @@ import { useEnterPasswordStyles } from './enter-password.styles';
export const EnterPassword = () => {
const styles = useEnterPasswordStyles();

const atBootsplash = useAtBootsplash();

const { unlock, unlockWithBiometry } = useAppLock();

const { biometryType } = useBiometryAvailability();
Expand All @@ -51,9 +52,10 @@ export const EnterPassword = () => {

usePageAnalytic(OverlayEnum.EnterPassword);

useDelayedEffect(HIDE_SPLASH_SCREEN_TIMEOUT, () => void (isBiometryAvailable && unlockWithBiometry()), [
isBiometryAvailable
]);
useEffect(
() => void (!atBootsplash && isBiometryAvailable && unlockWithBiometry()),
[isBiometryAvailable, atBootsplash]
);

return (
<ScreenContainer style={styles.root} keyboardBehavior="padding" isFullScreenMode={true}>
Expand Down
2 changes: 1 addition & 1 deletion src/shelter/app-lock/app-lock.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export const AppLockContextProvider: FC = ({ children }) => {

return undefined;
})
.catch(() => undefined);
.catch(error => void console.error(error));

isDefined(password) && unlock(password);
}, [unlock]);
Expand Down
2 changes: 1 addition & 1 deletion src/shelter/shelter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ export class Shelter {

static disableBiometryPassword$ = () => from(Keychain.resetGenericPassword(getKeychainOptions(PASSWORD_STORAGE_KEY)));

static getBiometryPassword = () => Keychain.getGenericPassword(biometryKeychainOptions);
static getBiometryPassword = async () => Keychain.getGenericPassword(biometryKeychainOptions);

static isPasswordCorrect$ = (password: string) =>
hashPassword$(password).pipe(map(passwordHash => passwordHash === Shelter._passwordHash$.getValue()));
Expand Down

0 comments on commit c33d784

Please sign in to comment.