Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Backups V2 Follow-up Fixes / Improvements #6213

Draft
wants to merge 24 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
c035b9f
remove useState that is getting wiped between renders
walmat Oct 18, 2024
ea2fd09
lots of provider structure changes
walmat Oct 19, 2024
3735f81
Merge branch 'develop' into @matthew/APP-1297
walmat Oct 25, 2024
4afed74
lots more progress on restructuring and code sharing
walmat Nov 6, 2024
fb913bc
more code quality improvements
walmat Nov 6, 2024
afc42bf
prevent App.tsx from re-rendering unless it needs to
walmat Nov 8, 2024
6946626
fix password not being pulled from local password keychain and add lo…
walmat Nov 8, 2024
9ea81dd
misc backups improvements
walmat Nov 8, 2024
fd16a13
Update .vscode/settings.json
walmat Nov 8, 2024
00d1bff
cleanup
walmat Nov 8, 2024
7016d47
Merge branch '@matthew/APP-1297' of https://github.com/rainbow-me/rai…
walmat Nov 8, 2024
5420054
fix lint
walmat Nov 11, 2024
c20670c
Merge branch 'develop' into @matthew/APP-1297
walmat Nov 14, 2024
5784cb2
fix overlay causing top leve re-renders
walmat Nov 14, 2024
0c81b5f
nav back to wallet screen on both new user restore / existing restore
walmat Nov 14, 2024
1fadaf5
convert cloud backup provider to zustand store, remove userData as it…
walmat Nov 16, 2024
a9948af
lots of cleanup
walmat Nov 18, 2024
5c5a848
add icon to indicate wrogn backup password
walmat Nov 18, 2024
6d7b6fa
simplify prompt to backup selected wallet
walmat Nov 18, 2024
9823919
more manual backup to cloud backup transitions
walmat Nov 18, 2024
7b18523
Update src/components/backup/RestoreCloudStep.tsx
walmat Nov 18, 2024
1f42ab9
reset backup provider to undefined if no condition is met
walmat Nov 18, 2024
466f3dc
adjust logic for displaying backed up status on Android when switchin…
walmat Nov 18, 2024
461ee79
more android tweaks
walmat Nov 18, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 23 additions & 11 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import '@/languages';
import * as Sentry from '@sentry/react-native';
import React, { useCallback, useEffect, useState } from 'react';
import React, { useCallback, useEffect, useState, memo } from 'react';
import { AppRegistry, Dimensions, LogBox, StyleSheet, View } from 'react-native';
import { Toaster } from 'sonner-native';
import { MobileWalletProtocolProvider } from '@coinbase/mobile-wallet-protocol-host';
Expand All @@ -9,7 +9,7 @@ import { useApplicationSetup } from '@/hooks/useApplicationSetup';
import { GestureHandlerRootView } from 'react-native-gesture-handler';
import { SafeAreaProvider, useSafeAreaInsets } from 'react-native-safe-area-context';
import { enableScreens } from 'react-native-screens';
import { connect, Provider as ReduxProvider } from 'react-redux';
import { connect, Provider as ReduxProvider, shallowEqual } from 'react-redux';
import { RecoilRoot } from 'recoil';
import PortalConsumer from '@/components/PortalConsumer';
import ErrorBoundary from '@/components/error-boundary/ErrorBoundary';
Expand All @@ -22,7 +22,7 @@ import * as keychain from '@/model/keychain';
import { Navigation } from '@/navigation';
import { PersistQueryClientProvider, persistOptions, queryClient } from '@/react-query';
import store, { AppDispatch, type AppState } from '@/redux/store';
import { MainThemeProvider, useTheme } from '@/theme/ThemeContext';
import { MainThemeProvider } from '@/theme/ThemeContext';
import { addressKey } from '@/utils/keychainConstants';
import { SharedValuesProvider } from '@/helpers/SharedValuesContext';
import { InitialRouteContext } from '@/navigation/initialRoute';
Expand All @@ -42,7 +42,7 @@ import { Address } from 'viem';
import { IS_ANDROID, IS_DEV } from '@/env';
import { prefetchDefaultFavorites } from '@/resources/favorites';
import Routes from '@/navigation/Routes';
import { BackendNetworks } from '@/components/BackendNetworks';
import { BackupsSync } from '@/state/sync/BackupsSync';

if (IS_DEV) {
reactNativeDisableYellowBox && LogBox.ignoreAllLogs();
Expand Down Expand Up @@ -70,27 +70,39 @@ function App({ walletReady }: AppProps) {
}, []);

return (
<Portal>
<>
<View style={[sx.container, { paddingBottom: IS_ANDROID ? bottom : 0 }]}>
{initialRoute && (
<InitialRouteContext.Provider value={initialRoute}>
<Routes ref={handleNavigatorRef} />
<PortalConsumer />
</InitialRouteContext.Provider>
)}
<OfflineToast />
<Toaster />
</View>
<NotificationsHandler walletReady={walletReady} />
<DeeplinkHandler initialRoute={initialRoute} walletReady={walletReady} />
<BackendNetworks />
</Portal>
<Portal />
<PortalConsumer />
Comment on lines +85 to +86
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are now no longer re-rendering the entire app when re-rendering

<BackupsSync />
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In charge of initial backup store sync on mount

</>
);
}

const AppWithRedux = connect<AppProps, AppDispatch, AppProps, AppState>(state => ({
walletReady: state.appState.walletReady,
}))(App);
const AppWithRedux = connect<AppProps, AppDispatch, AppProps, AppState>(
state => ({
walletReady: state.appState.walletReady,
}),
null,
null,
{
areStatesEqual: (next, prev) => {
// Only update if walletReady actually changed
return next.appState.walletReady === prev.appState.walletReady;
},
areOwnPropsEqual: shallowEqual,
}
)(memo(App));
Comment on lines +92 to +105
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we only really want to re-render the App when walletReady has changed.. this fixes that


function Root() {
const [initializing, setInitializing] = useState(true);
Expand Down
10 changes: 5 additions & 5 deletions src/components/PortalConsumer.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@ import React, { useEffect } from 'react';
import { LoadingOverlay } from './modal';
import { useWallets } from '@/hooks';
import { sheetVerticalOffset } from '@/navigation/effects';
import { usePortal } from '@/react-native-cool-modals/Portal';
import { portalStore } from '@/state/portal/portal';

export default function PortalConsumer() {
const { isWalletLoading } = useWallets();
const { setComponent, hide } = usePortal();

useEffect(() => {
if (isWalletLoading) {
setComponent(<LoadingOverlay paddingTop={sheetVerticalOffset} title={isWalletLoading} />, true);
portalStore.getState().setComponent(<LoadingOverlay paddingTop={sheetVerticalOffset} title={isWalletLoading} />, true);
}
return hide;
}, [hide, isWalletLoading, setComponent]);
return portalStore.getState().hide;
}, [isWalletLoading]);

return null;
}
54 changes: 28 additions & 26 deletions src/components/backup/AddWalletToCloudBackupStep.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,38 +9,40 @@ import { ButtonPressAnimation } from '../animations';
import Routes from '@/navigation/routesNames';
import { useNavigation } from '@/navigation';
import { useWallets } from '@/hooks';
import { WalletCountPerType, useVisibleWallets } from '@/screens/SettingsSheet/useVisibleWallets';
import { format } from 'date-fns';
import { useCreateBackup } from './useCreateBackup';
import { login } from '@/handlers/cloudBackup';
import { useCreateBackup } from '@/components/backup/useCreateBackup';
import { backupsStore } from '@/state/backups/backups';
import { executeFnIfCloudBackupAvailable } from '@/model/backup';

const imageSize = 72;

export default function AddWalletToCloudBackupStep() {
const { goBack } = useNavigation();
const { wallets, selectedWallet } = useWallets();
const { selectedWallet } = useWallets();
const createBackup = useCreateBackup();

const walletTypeCount: WalletCountPerType = {
phrase: 0,
privateKey: 0,
};

const { lastBackupDate } = useVisibleWallets({ wallets, walletTypeCount });

const { onSubmit } = useCreateBackup({
walletId: selectedWallet.id,
navigateToRoute: {
route: Routes.SETTINGS_SHEET,
params: {
screen: Routes.SETTINGS_SECTION_BACKUP,
},
},
});
const { mostRecentBackup } = backupsStore(state => ({
mostRecentBackup: state.mostRecentBackup,
}));

const potentiallyLoginAndSubmit = useCallback(async () => {
await login();
return onSubmit({});
}, [onSubmit]);
const result = await executeFnIfCloudBackupAvailable({
fn: () =>
createBackup({
walletId: selectedWallet.id,
navigateToRoute: {
route: Routes.SETTINGS_SHEET,
params: {
screen: Routes.SETTINGS_SECTION_BACKUP,
},
},
}),
});

if (result) {
goBack();
}
}, [createBackup, goBack, selectedWallet.id]);

const onMaybeLater = useCallback(() => goBack(), [goBack]);

Expand Down Expand Up @@ -70,7 +72,7 @@ export default function AddWalletToCloudBackupStep() {
<Separator color="separatorSecondary" thickness={1} />
</Bleed>

<ButtonPressAnimation scaleTo={0.95} onPress={() => potentiallyLoginAndSubmit().then(success => success && goBack())}>
<ButtonPressAnimation scaleTo={0.95} onPress={potentiallyLoginAndSubmit}>
<Box alignItems="center" justifyContent="center" paddingTop={'24px'} paddingBottom={'24px'}>
<Box alignItems="center" justifyContent="center" width="full">
<Inline alignHorizontal="justify" alignVertical="center" wrap={false}>
Expand Down Expand Up @@ -105,13 +107,13 @@ export default function AddWalletToCloudBackupStep() {
<Separator color="separatorSecondary" thickness={1} />
</Bleed>

{lastBackupDate && (
{mostRecentBackup && (
<Box alignItems="center" justifyContent="center" paddingTop={'24px'} paddingBottom={'24px'}>
<Box alignItems="center" justifyContent="center" width="full">
<Inline alignHorizontal="justify" alignVertical="center" wrap={false}>
<Text color={'labelTertiary'} size="15pt" weight="medium">
{lang.t(lang.l.back_up.cloud.latest_backup, {
date: format(lastBackupDate, "M/d/yy 'at' h:mm a"),
date: format(new Date(mostRecentBackup.lastModified), "M/d/yy 'at' h:mm a"),
})}
</Text>
</Inline>
Expand Down
81 changes: 20 additions & 61 deletions src/components/backup/BackupChooseProviderStep.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import React from 'react';
import { useCreateBackup } from '@/components/backup/useCreateBackup';
import { Bleed, Box, Inline, Inset, Separator, Stack, Text } from '@/design-system';
import * as lang from '@/languages';
import { ImgixImage } from '../images';
Expand All @@ -16,74 +15,34 @@ import { SETTINGS_BACKUP_ROUTES } from '@/screens/SettingsSheet/components/Backu
import { useWallets } from '@/hooks';
import walletTypes from '@/helpers/walletTypes';
import walletBackupTypes from '@/helpers/walletBackupTypes';
import { IS_ANDROID } from '@/env';
import { GoogleDriveUserData, getGoogleAccountUserData, isCloudBackupAvailable, login } from '@/handlers/cloudBackup';
import { WrappedAlert as Alert } from '@/helpers/alert';
import { RainbowError, logger } from '@/logger';
import { Linking } from 'react-native';
import { useCreateBackup } from '@/components/backup/useCreateBackup';
import { backupsStore, CloudBackupState } from '@/state/backups/backups';
import { executeFnIfCloudBackupAvailable } from '@/model/backup';

const imageSize = 72;

export default function BackupSheetSectionNoProvider() {
const { colors } = useTheme();
const { navigate, goBack } = useNavigation();
const { selectedWallet } = useWallets();
const createBackup = useCreateBackup();
const { status } = backupsStore(state => ({
status: state.status,
}));

const { onSubmit, loading } = useCreateBackup({
walletId: selectedWallet.id,
navigateToRoute: {
route: Routes.SETTINGS_SHEET,
params: {
screen: Routes.SETTINGS_SECTION_BACKUP,
},
},
});

const onCloudBackup = async () => {
if (loading !== 'none') {
return;
}
// NOTE: On Android we need to make sure the user is signed into a Google account before trying to backup
// otherwise we'll fake backup and it's confusing...
if (IS_ANDROID) {
try {
await login();
getGoogleAccountUserData().then((accountDetails: GoogleDriveUserData | undefined) => {
if (!accountDetails) {
Alert.alert(lang.t(lang.l.back_up.errors.no_account_found));
return;
}
});
} catch (e) {
logger.error(new RainbowError('[BackupSheetSectionNoProvider]: No account found'), {
error: e,
});
Alert.alert(lang.t(lang.l.back_up.errors.no_account_found));
}
} else {
const isAvailable = await isCloudBackupAvailable();
if (!isAvailable) {
Alert.alert(
lang.t(lang.l.modal.back_up.alerts.cloud_not_enabled.label),
lang.t(lang.l.modal.back_up.alerts.cloud_not_enabled.description),
[
{
onPress: () => {
Linking.openURL('https://support.apple.com/en-us/HT204025');
},
text: lang.t(lang.l.modal.back_up.alerts.cloud_not_enabled.show_me),
},
{
style: 'cancel',
text: lang.t(lang.l.modal.back_up.alerts.cloud_not_enabled.no_thanks),
const onCloudBackup = () => {
executeFnIfCloudBackupAvailable({
fn: () =>
createBackup({
walletId: selectedWallet.id,
navigateToRoute: {
route: Routes.SETTINGS_SHEET,
params: {
screen: Routes.SETTINGS_SECTION_BACKUP,
},
]
);
return;
}
}

onSubmit({});
},
}),
});
};

const onManualBackup = async () => {
Expand Down Expand Up @@ -117,7 +76,7 @@ export default function BackupSheetSectionNoProvider() {
</Bleed>

{/* replace this with BackUpMenuButton */}
<ButtonPressAnimation scaleTo={0.95} onPress={onCloudBackup}>
<ButtonPressAnimation disabled={status !== CloudBackupState.Ready} scaleTo={0.95} onPress={onCloudBackup}>
<Box alignItems="flex-start" justifyContent="flex-start" paddingTop={'24px'} paddingBottom={'36px'} gap={8}>
<Box justifyContent="center" width="full">
<Inline alignHorizontal="justify" alignVertical="center" wrap={false}>
Expand Down
27 changes: 12 additions & 15 deletions src/components/backup/BackupSheet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import { SimpleSheet } from '@/components/sheet/SimpleSheet';
import AddWalletToCloudBackupStep from '@/components/backup/AddWalletToCloudBackupStep';
import BackupManuallyStep from './BackupManuallyStep';
import { getHeightForStep } from '@/navigation/config';
import { CloudBackupProvider } from './CloudBackupProvider';

type BackupSheetParams = {
BackupSheet: {
Expand Down Expand Up @@ -40,19 +39,17 @@ export default function BackupSheet() {
}, [step]);

return (
<CloudBackupProvider>
<BackgroundProvider color="surfaceSecondary">
{({ backgroundColor }) => (
<SimpleSheet
testID={'backup-sheet'}
backgroundColor={backgroundColor as string}
customHeight={getHeightForStep(step)}
scrollEnabled={false}
>
{renderStep()}
</SimpleSheet>
)}
</BackgroundProvider>
</CloudBackupProvider>
<BackgroundProvider color="surfaceSecondary">
{({ backgroundColor }) => (
<SimpleSheet
testID={'backup-sheet'}
backgroundColor={backgroundColor as string}
customHeight={getHeightForStep(step)}
scrollEnabled={false}
>
{renderStep()}
</SimpleSheet>
)}
</BackgroundProvider>
);
}
Loading
Loading