From ad27b695885f71a2d7e09f7a40dee25990a1c5b3 Mon Sep 17 00:00:00 2001 From: alex-seleznov Date: Thu, 22 Dec 2022 22:10:07 +0200 Subject: [PATCH 1/5] [tech] Fix postinstall script on Linux --- postinstall.sh | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/postinstall.sh b/postinstall.sh index d794a3c7e..7892690db 100644 --- a/postinstall.sh +++ b/postinstall.sh @@ -3,10 +3,14 @@ search_string="compile 'com.facebook.react:react-native:+'" replace_string="implementation 'com.facebook.react:react-native:+'" -sed -i "" "s/$search_string/$replace_string/" node_modules/react-native-os/android/build.gradle -sed -i "" "s/$search_string/$replace_string/" node_modules/react-native-scrypt/android/build.gradle +if [ "$(expr substr $(uname -s) 1 5)" != "Linux" ]; then + sed_mac_arg=true +fi + +sed -i ${sed_mac_arg:+""} "s/$search_string/$replace_string/" node_modules/react-native-os/android/build.gradle +sed -i ${sed_mac_arg:+""} "s/$search_string/$replace_string/" node_modules/react-native-scrypt/android/build.gradle deprecated_types_replace_string="} from 'react-native'\nimport { ViewPropTypes } from 'deprecated-react-native-prop-types'" -sed -i "" "s/ ViewPropTypes,//" node_modules/react-native-camera/src/RNCamera.js -sed -i "" "s/} from 'react-native';/$deprecated_types_replace_string/" node_modules/react-native-camera/src/RNCamera.js +sed -i ${sed_mac_arg:+""} "s/ ViewPropTypes,//" node_modules/react-native-camera/src/RNCamera.js +sed -i ${sed_mac_arg:+""} "s/} from 'react-native';/$deprecated_types_replace_string/" node_modules/react-native-camera/src/RNCamera.js From d8c6c64c3c3cf405cbf5e7664db922304b001588 Mon Sep 17 00:00:00 2001 From: alex-seleznov Date: Thu, 19 Jan 2023 09:17:31 +0200 Subject: [PATCH 2/5] TW-346: Fix unlock after minimize. With bootsplash screen hiding earlier --- src/app/app.tsx | 13 +++++++++---- src/hooks/use-delayed-effect.hook.ts | 9 --------- src/navigator/root-stack.tsx | 8 ++++++-- src/screens/enter-password/enter-password.tsx | 17 ++++++++++------- 4 files changed, 25 insertions(+), 22 deletions(-) delete mode 100644 src/hooks/use-delayed-effect.hook.ts diff --git a/src/app/app.tsx b/src/app/app.tsx index bd076f4b2..bd4e126fc 100644 --- a/src/app/app.tsx +++ b/src/app/app.tsx @@ -1,5 +1,5 @@ import { AnalyticsProvider } from '@segment/analytics-react-native'; -import React from 'react'; +import React, { useEffect, useState } from 'react'; import { LogBox } from 'react-native'; import { hide } from 'react-native-bootsplash'; import { GestureHandlerRootView } from 'react-native-gesture-handler'; @@ -11,7 +11,6 @@ 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 { RootStackScreen } from '../navigator/root-stack'; import { AppLockContextProvider } from '../shelter/app-lock/app-lock'; import { persistor, store } from '../store/store'; @@ -25,7 +24,13 @@ enableScreens(); LogBox.ignoreAllLogs(); export const App = () => { - useDelayedEffect(HIDE_SPLASH_SCREEN_TIMEOUT, () => void hide({ fade: true }), []); + const [atBootsplash, setAtBootsplash] = useState(true); + useEffect(() => { + (async () => { + await hide({ fade: true }); + setTimeout(() => void setAtBootsplash(false), HIDE_SPLASH_SCREEN_TIMEOUT); + })(); + }, []); return ( @@ -36,7 +41,7 @@ export const App = () => { - + diff --git a/src/hooks/use-delayed-effect.hook.ts b/src/hooks/use-delayed-effect.hook.ts deleted file mode 100644 index 6cebc1bce..000000000 --- a/src/hooks/use-delayed-effect.hook.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { DependencyList, EffectCallback, useEffect } from 'react'; - -export const useDelayedEffect = (ms: number, effect: EffectCallback, deps?: DependencyList) => { - useEffect(() => { - const timeoutId = setTimeout(effect, ms); - - return () => clearTimeout(timeoutId); - }, deps); -}; diff --git a/src/navigator/root-stack.tsx b/src/navigator/root-stack.tsx index 7f251fbc5..5b6ede7b3 100644 --- a/src/navigator/root-stack.tsx +++ b/src/navigator/root-stack.tsx @@ -50,7 +50,11 @@ type RootStackParamList = { MainStack: undefined } & ModalsParamList; const RootStack = createStackNavigator(); -export const RootStackScreen = () => { +interface Props { + atBootsplash: boolean; +} + +export const RootStackScreen = ({ atBootsplash }: Props) => { const { isLocked } = useAppLock(); const isShowLoader = useIsShowLoaderSelector(); const isAuthorised = useIsAuthorisedSelector(); @@ -159,7 +163,7 @@ export const RootStackScreen = () => { {isSplash && } - {isAuthorised && isLocked && } + {isAuthorised && isLocked && } {!isPasscode && } {isForceUpdateNeeded && } {isAppCheckFailed && } diff --git a/src/screens/enter-password/enter-password.tsx b/src/screens/enter-password/enter-password.tsx index faa0f8192..db7e90ff8 100644 --- a/src/screens/enter-password/enter-password.tsx +++ b/src/screens/enter-password/enter-password.tsx @@ -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'; @@ -13,10 +13,8 @@ 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 { usePasswordLock } from '../../hooks/use-password-lock.hook'; import { useResetDataHandler } from '../../hooks/use-reset-data-handler.hook'; import { OverlayEnum } from '../../navigator/enums/overlay.enum'; @@ -33,7 +31,11 @@ import { } from './enter-password.form'; import { useEnterPasswordStyles } from './enter-password.styles'; -export const EnterPassword = () => { +interface Props { + atBootsplash: boolean; +} + +export const EnterPassword = ({ atBootsplash }: Props) => { const styles = useEnterPasswordStyles(); const { unlock, unlockWithBiometry } = useAppLock(); @@ -51,9 +53,10 @@ export const EnterPassword = () => { usePageAnalytic(OverlayEnum.EnterPassword); - useDelayedEffect(HIDE_SPLASH_SCREEN_TIMEOUT, () => void (isBiometryAvailable && unlockWithBiometry()), [ - isBiometryAvailable - ]); + useEffect( + () => void (!atBootsplash && isBiometryAvailable && unlockWithBiometry()), + [isBiometryAvailable, atBootsplash] + ); return ( From 7dc9a7d8802a4c0d80ebb4d2cc6a530e0946c8d2 Mon Sep 17 00:00:00 2001 From: alex-seleznov Date: Thu, 19 Jan 2023 09:20:49 +0200 Subject: [PATCH 3/5] TW-346: Fix unlock after minimize. With disabling 'warm-up' in 'react-native-keychain' --- android/app/build.gradle | 1 + .../src/main/java/com/templewallet/MainApplication.java | 7 +++++++ android/settings.gradle | 4 ++++ react-native.config.js | 9 ++++++++- src/shelter/app-lock/app-lock.tsx | 2 +- src/shelter/shelter.ts | 2 +- 6 files changed, 22 insertions(+), 3 deletions(-) diff --git a/android/app/build.gradle b/android/app/build.gradle index 52b4693c4..e20961056 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -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" diff --git a/android/app/src/main/java/com/templewallet/MainApplication.java b/android/app/src/main/java/com/templewallet/MainApplication.java index 9ce3fa3ff..423381e21 100644 --- a/android/app/src/main/java/com/templewallet/MainApplication.java +++ b/android/app/src/main/java/com/templewallet/MainApplication.java @@ -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; @@ -28,6 +30,11 @@ public boolean getUseDeveloperSupport() { protected List getPackages() { @SuppressWarnings("UnnecessaryLocalVariable") List 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; diff --git a/android/settings.gradle b/android/settings.gradle index 77c00b895..c25f09fe6 100644 --- a/android/settings.gradle +++ b/android/settings.gradle @@ -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") { diff --git a/react-native.config.js b/react-native.config.js index 4ab64639f..95a6cb84f 100644 --- a/react-native.config.js +++ b/react-native.config.js @@ -1,3 +1,10 @@ module.exports = { - assets: ['./src/assets/fonts/'] + assets: ['./src/assets/fonts/'], + dependencies: { + 'react-native-keychain': { + platforms: { + android: null + } + } + } }; diff --git a/src/shelter/app-lock/app-lock.tsx b/src/shelter/app-lock/app-lock.tsx index 73c0adb14..a966a9831 100644 --- a/src/shelter/app-lock/app-lock.tsx +++ b/src/shelter/app-lock/app-lock.tsx @@ -46,7 +46,7 @@ export const AppLockContextProvider: FC = ({ children }) => { return undefined; }) - .catch(() => undefined); + .catch(error => void console.error(error)); isDefined(password) && unlock(password); }, [unlock]); diff --git a/src/shelter/shelter.ts b/src/shelter/shelter.ts index e29b7fb3c..dbd01bd39 100644 --- a/src/shelter/shelter.ts +++ b/src/shelter/shelter.ts @@ -181,7 +181,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())); From f4f7b05893a59e075576f5d57dc472c8203257df Mon Sep 17 00:00:00 2001 From: alex-seleznov Date: Sun, 22 Jan 2023 23:30:46 +0200 Subject: [PATCH 4/5] TW-346: Fix unlock after minimize. Refactor --- .editorconfig copy | 9 +++ src/app/app.tsx | 57 ++++++++----------- src/hooks/use-hide-bootsplash.tsx | 23 ++++++++ src/navigator/root-stack.tsx | 8 +-- src/screens/enter-password/enter-password.tsx | 9 ++- 5 files changed, 62 insertions(+), 44 deletions(-) create mode 100755 .editorconfig copy create mode 100644 src/hooks/use-hide-bootsplash.tsx diff --git a/.editorconfig copy b/.editorconfig copy new file mode 100755 index 000000000..cb8b48c70 --- /dev/null +++ b/.editorconfig copy @@ -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 \ No newline at end of file diff --git a/src/app/app.tsx b/src/app/app.tsx index bd4e126fc..1824a0699 100644 --- a/src/app/app.tsx +++ b/src/app/app.tsx @@ -1,7 +1,6 @@ import { AnalyticsProvider } from '@segment/analytics-react-native'; -import React, { useEffect, useState } from 'react'; +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'; @@ -9,8 +8,8 @@ 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 { 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'; @@ -23,33 +22,25 @@ initSentry(); enableScreens(); LogBox.ignoreAllLogs(); -export const App = () => { - const [atBootsplash, setAtBootsplash] = useState(true); - useEffect(() => { - (async () => { - await hide({ fade: true }); - setTimeout(() => void setAtBootsplash(false), HIDE_SPLASH_SCREEN_TIMEOUT); - })(); - }, []); - - return ( - - - - - - - - - - - - - - - - - - - ); -}; +export const App = () => ( + + + + + + + + + + + + + + + + + + + + +); diff --git a/src/hooks/use-hide-bootsplash.tsx b/src/hooks/use-hide-bootsplash.tsx new file mode 100644 index 000000000..249206b7b --- /dev/null +++ b/src/hooks/use-hide-bootsplash.tsx @@ -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(false); + +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 {children}; +}; + +export const useAtBootsplash = () => useContext(context); diff --git a/src/navigator/root-stack.tsx b/src/navigator/root-stack.tsx index 5b6ede7b3..7f251fbc5 100644 --- a/src/navigator/root-stack.tsx +++ b/src/navigator/root-stack.tsx @@ -50,11 +50,7 @@ type RootStackParamList = { MainStack: undefined } & ModalsParamList; const RootStack = createStackNavigator(); -interface Props { - atBootsplash: boolean; -} - -export const RootStackScreen = ({ atBootsplash }: Props) => { +export const RootStackScreen = () => { const { isLocked } = useAppLock(); const isShowLoader = useIsShowLoaderSelector(); const isAuthorised = useIsAuthorisedSelector(); @@ -163,7 +159,7 @@ export const RootStackScreen = ({ atBootsplash }: Props) => { {isSplash && } - {isAuthorised && isLocked && } + {isAuthorised && isLocked && } {!isPasscode && } {isForceUpdateNeeded && } {isAppCheckFailed && } diff --git a/src/screens/enter-password/enter-password.tsx b/src/screens/enter-password/enter-password.tsx index db7e90ff8..1a5c8dafc 100644 --- a/src/screens/enter-password/enter-password.tsx +++ b/src/screens/enter-password/enter-password.tsx @@ -15,6 +15,7 @@ import { Quote } from '../../components/quote/quote'; import { ScreenContainer } from '../../components/screen-container/screen-container'; import { MAX_PASSWORD_ATTEMPTS } from '../../config/security'; import { FormPasswordInput } from '../../form/form-password-input'; +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'; @@ -31,13 +32,11 @@ import { } from './enter-password.form'; import { useEnterPasswordStyles } from './enter-password.styles'; -interface Props { - atBootsplash: boolean; -} - -export const EnterPassword = ({ atBootsplash }: Props) => { +export const EnterPassword = () => { const styles = useEnterPasswordStyles(); + const atBootsplash = useAtBootsplash(); + const { unlock, unlockWithBiometry } = useAppLock(); const { biometryType } = useBiometryAvailability(); From 3fd67b470a4c666eff3d9aa78de6fdae37ffe88a Mon Sep 17 00:00:00 2001 From: alex-seleznov Date: Mon, 23 Jan 2023 13:52:01 +0200 Subject: [PATCH 5/5] TW-346: Fix unlock after minimize. Refactor. Fix --- src/hooks/use-hide-bootsplash.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hooks/use-hide-bootsplash.tsx b/src/hooks/use-hide-bootsplash.tsx index 249206b7b..e258f8494 100644 --- a/src/hooks/use-hide-bootsplash.tsx +++ b/src/hooks/use-hide-bootsplash.tsx @@ -3,7 +3,7 @@ import { hide } from 'react-native-bootsplash'; import { HIDE_SPLASH_SCREEN_TIMEOUT } from '../config/animation'; -const context = createContext(false); +const context = createContext(true); const Provider = context.Provider;