Skip to content

Commit

Permalink
CP-9314: Set up dynamic app switch (#2016)
Browse files Browse the repository at this point in the history
  • Loading branch information
atn4z7 authored Oct 28, 2024
1 parent b2d8f35 commit 41e0d11
Show file tree
Hide file tree
Showing 17 changed files with 231 additions and 126 deletions.
54 changes: 54 additions & 0 deletions packages/core-mobile/AppSwitcher.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import React, { useState, useCallback, useMemo } from 'react'
import { Alert, View, PanResponder } from 'react-native'
import OldApp from 'ContextApp'
import NewApp from 'new/ContextApp'
import { commonStorage } from 'utils/mmkv'
import { StorageKey } from 'resources/Constants'
import DeviceInfoService from 'services/deviceInfo/DeviceInfoService'
import DevDebuggingConfig from 'utils/debugging/DevDebuggingConfig'

const bundleId = DeviceInfoService.getBundleId()
const isInternalBuild =
bundleId === 'org.avalabs.avaxwallet.internal' ||
bundleId === 'com.avaxwallet.internal'

export const AppSwitcher = (): React.JSX.Element => {
const [isNewApp, setIsNewApp] = useState(
commonStorage.getBoolean(StorageKey.K2_ALPINE)
)

const switchApp = useCallback(() => {
const newValue = !isNewApp
commonStorage.set(StorageKey.K2_ALPINE, newValue)
setIsNewApp(newValue)
}, [isNewApp, setIsNewApp])

const panResponder = useMemo(
() =>
PanResponder.create({
onStartShouldSetPanResponder: (evt, gestureState) => {
if (gestureState.numberActiveTouches === 2) {
Alert.alert('Switch App Experience?', '', [
{
text: 'Cancel',
style: 'cancel'
},
{ text: 'OK', onPress: switchApp }
])
}

return true
}
}),
[switchApp]
)

// only allow switching to new app on internal builds
if (!isInternalBuild) return <OldApp />

return (
<View style={{ flex: 1 }} {...panResponder.panHandlers}>
{DevDebuggingConfig.K2_ALPINE || isNewApp ? <NewApp /> : <OldApp />}
</View>
)
}
32 changes: 2 additions & 30 deletions packages/core-mobile/app/App.tsx
Original file line number Diff line number Diff line change
@@ -1,43 +1,15 @@
import React, { useState } from 'react'
import {
KeyboardAvoidingView,
LogBox,
Platform,
SafeAreaView,
UIManager
} from 'react-native'
import { KeyboardAvoidingView, Platform, SafeAreaView } from 'react-native'
import RootScreenStack from 'navigation/RootScreenStack'
import { NavigationContainer } from '@react-navigation/native'
import { useApplicationContext } from 'contexts/ApplicationContext'
import useDevDebugging from 'utils/debugging/DevDebugging'
import 'utils/debugging/wdyr'
import { navigationRef } from 'utils/Navigation'
import SentryService from 'services/sentry/SentryService'
import DataDogService from 'services/datadog/DataDogService'
import Logger, { LogLevel } from 'utils/Logger'

Logger.setLevel(__DEV__ ? LogLevel.TRACE : LogLevel.ERROR)

LogBox.ignoreLogs([
'Require cycle:',
"Can't perform",
'new',
'Non-serializable'
])

SentryService.init()

Platform.OS === 'android' &&
UIManager.setLayoutAnimationEnabledExperimental &&
UIManager.setLayoutAnimationEnabledExperimental(false)
import Logger from 'utils/Logger'

function App(): JSX.Element {
const { configure } = useDevDebugging()
const isProduction = process.env.NODE_ENV === 'production'
if (!isProduction) {
configure()
}

const context = useApplicationContext()
const [backgroundStyle] = useState(context.appBackgroundStyle)

Expand Down
17 changes: 5 additions & 12 deletions packages/core-mobile/app/ContextApp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import Toast from 'react-native-toast-notifications'
import JailMonkey from 'jail-monkey'
import { RootSiblingParent } from 'react-native-root-siblings'
import { K2ThemeProvider } from '@avalabs/k2-mobile'
import { K2AlpineThemeProvider } from '@avalabs/k2-alpine'
import JailbrokenWarning from 'screens/onboarding/JailbrokenWarning'
import { PosthogContextProvider } from 'contexts/PosthogContext'
import { StatusBar, View } from 'react-native'
Expand All @@ -23,10 +22,6 @@ import SentryService from 'services/sentry/SentryService'
import CoreSplash from 'assets/icons/core_splash.svg'
import { useMigrateFromAsyncStorage } from 'hooks/useMigrateFromAsyncStorage'

if (__DEV__) {
require('../ReactotronConfig')
}

function setToast(toast: Toast): void {
global.toast = toast
}
Expand All @@ -38,13 +33,11 @@ const ContextProviders: FC<PropsWithChildren> = ({ children }) => (
<EncryptedStoreProvider>
<ReactQueryProvider>
<PosthogContextProvider>
<K2AlpineThemeProvider colorScheme={'dark'}>
<K2ThemeProvider>
<ApplicationContextProvider>
<DeeplinkContextProvider>{children}</DeeplinkContextProvider>
</ApplicationContextProvider>
</K2ThemeProvider>
</K2AlpineThemeProvider>
<K2ThemeProvider>
<ApplicationContextProvider>
<DeeplinkContextProvider>{children}</DeeplinkContextProvider>
</ApplicationContextProvider>
</K2ThemeProvider>
</PosthogContextProvider>
</ReactQueryProvider>
</EncryptedStoreProvider>
Expand Down
5 changes: 3 additions & 2 deletions packages/core-mobile/app/contexts/PosthogContext/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
} from 'store/posthog/slice'
import AnalyticsService from 'services/analytics/AnalyticsService'
import { commonStorage } from 'utils/mmkv'
import { StorageKey } from 'resources/Constants'

export const PosthogContext = createContext<PosthogContextState>(
{} as PosthogContextState
Expand Down Expand Up @@ -62,8 +63,8 @@ export const PosthogContextProvider = ({

const { timeoutPassed } = useAppBackgroundTracker({
timeoutMs: 30 * 60 * 1000,
getTime: () => commonStorage.getString('POSTHOG_SUSPENDED'),
setTime: time => commonStorage.set('POSTHOG_SUSPENDED', time)
getTime: () => commonStorage.getString(StorageKey.POSTHOG_SUSPENDED),
setTime: time => commonStorage.set(StorageKey.POSTHOG_SUSPENDED, time)
})

const [analyticsConsent, setAnalyticsConsent] = useState<
Expand Down
8 changes: 8 additions & 0 deletions packages/core-mobile/app/new/App.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { ExpoRoot } from 'expo-router'
import React from 'react'

export const App = () => {
const ctx = require.context('./routes')

return <ExpoRoot context={ctx} />
}
77 changes: 77 additions & 0 deletions packages/core-mobile/app/new/ContextApp.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/**
* Context wrapper for App
**/
import React, { FC, PropsWithChildren, useEffect, useState } from 'react'
import * as Sentry from '@sentry/react-native'
import Toast from 'react-native-toast-notifications'
import JailMonkey from 'jail-monkey'
import { RootSiblingParent } from 'react-native-root-siblings'
import JailbrokenWarning from 'screens/onboarding/JailbrokenWarning'
import { PosthogContextProvider } from 'contexts/PosthogContext'
import { StatusBar } from 'react-native'
import { EncryptedStoreProvider } from 'contexts/EncryptedStoreProvider'
import { TopLevelErrorFallback } from 'components/TopLevelErrorFallback'
import { GestureHandlerRootView } from 'react-native-gesture-handler'
import { ReactQueryProvider } from 'contexts/ReactQueryProvider'
import SentryService from 'services/sentry/SentryService'
import { App } from './App'

function setToast(toast: Toast): void {
global.toast = toast
}

/**
* Aggregate all the top-level context providers for better readability.
*/
// TODO: add DeeplinkContextProvider
const ContextProviders: FC<PropsWithChildren> = ({ children }) => (
<EncryptedStoreProvider>
<ReactQueryProvider>
<PosthogContextProvider>{children}</PosthogContextProvider>
</ReactQueryProvider>
</EncryptedStoreProvider>
)

const ContextApp = (): JSX.Element => {
// TODO: convert TopLevelErrorFallback to new design
return (
<Sentry.ErrorBoundary fallback={<TopLevelErrorFallback />}>
<StatusBar barStyle={'light-content'} backgroundColor="black" />
<ContextProviders>
<JailBrokenCheck>
<GestureHandlerRootView style={{ flex: 1 }}>
<RootSiblingParent>
<App />
</RootSiblingParent>
</GestureHandlerRootView>
</JailBrokenCheck>
<Toast
ref={ref => {
ref && setToast(ref)
}}
offsetTop={30}
normalColor={'00FFFFFF'}
/>
</ContextProviders>
</Sentry.ErrorBoundary>
)
}

const JailBrokenCheck: FC<PropsWithChildren> = ({ children }) => {
const [showJailBroken, setShowJailBroken] = useState(false)

useEffect(() => {
if (!__DEV__ && JailMonkey.isJailBroken()) {
setShowJailBroken(true)
}
}, [])

if (showJailBroken) {
// TODO: convert JailbrokenWarning to new design
return <JailbrokenWarning onOK={() => setShowJailBroken(false)} />
}

return <>{children}</>
}

export default SentryService.isAvailable ? Sentry.wrap(ContextApp) : ContextApp
7 changes: 6 additions & 1 deletion packages/core-mobile/app/resources/Constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,12 @@ export enum COLORS_NIGHT {
blueLight = '#6AC0FF'
}

export const SECURE_ACCESS_SET = 'secureAccessSet'
export enum StorageKey {
SECURE_ACCESS_SET = 'secureAccessSet',
POSTHOG_SUSPENDED = 'POSTHOG_SUSPENDED',
HAS_MIGRATED_FROM_ASYNC_STORAGE = 'hasMigratedFromAsyncStorage',
K2_ALPINE = 'k2Alpine'
}

export const CORE_UNIVERSAL_LINK_HOSTS = ['core.app', 'test.core.app']

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { View } from 'react-native'
import { useApplicationContext } from 'contexts/ApplicationContext'
import AvaListItem from 'components/AvaListItem'
import BiometricsSDK from 'utils/BiometricsSDK'
import { SECURE_ACCESS_SET } from 'resources/Constants'
import { StorageKey } from 'resources/Constants'
import Switch from 'components/Switch'
import { useDispatch, useSelector } from 'react-redux'
import {
Expand Down Expand Up @@ -42,7 +42,7 @@ function SecurityPrivacy({
})
.catch(Logger.error)

const type = commonStorage.getString(SECURE_ACCESS_SET)
const type = commonStorage.getString(StorageKey.SECURE_ACCESS_SET)
if (type) {
setIsBiometricSwitchEnabled(type === 'BIO')
} else {
Expand All @@ -55,7 +55,7 @@ function SecurityPrivacy({
if (value) {
onTurnOnBiometrics()
} else {
commonStorage.set(SECURE_ACCESS_SET, 'PIN')
commonStorage.set(StorageKey.SECURE_ACCESS_SET, 'PIN')
}
}

Expand Down
Loading

0 comments on commit 41e0d11

Please sign in to comment.