Skip to content

Commit

Permalink
Merge 93bca72 into 7dc1b03
Browse files Browse the repository at this point in the history
  • Loading branch information
greg-schrammel authored Dec 10, 2024
2 parents 7dc1b03 + 93bca72 commit 48bcd19
Show file tree
Hide file tree
Showing 5 changed files with 248 additions and 111 deletions.
8 changes: 8 additions & 0 deletions src/languages/en_US.json
Original file line number Diff line number Diff line change
Expand Up @@ -2606,6 +2606,14 @@
"my_account_address": "My account address:",
"network_title": "Network",
"new": {
"choose_wallet_group": {
"title": "Choose Wallet Group",
"description": "Choose the wallet group you’d like to create a new wallet within, or create a new one."
},
"new_wallet_group": {
"title": "New Wallet Group",
"description": "Create a new wallet group"
},
"add_wallet_sheet": {
"options": {
"cloud": {
Expand Down
11 changes: 11 additions & 0 deletions src/navigation/AddWalletNavigator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { ImportOrWatchWalletSheet, ImportOrWatchWalletSheetParams } from '@/scre
import { BackgroundProvider } from '@/design-system';
import { RouteProp, useRoute } from '@react-navigation/native';
import { SimpleSheet } from '@/components/sheet/SimpleSheet';
import { ChooseWalletGroup } from './ChooseWalletGroup';

const Swipe = createMaterialTopTabNavigator();

Expand Down Expand Up @@ -41,6 +42,16 @@ export const AddWalletNavigator = () => {
},
}}
/>
<Swipe.Screen
component={ChooseWalletGroup}
initialParams={{ isFirstWallet }}
name={Routes.CHOOSE_WALLET_GROUP}
listeners={{
focus: () => {
setScrollEnabled(true);
},
}}
/>
<Swipe.Screen
component={ImportOrWatchWalletSheet}
initialParams={{ type }}
Expand Down
225 changes: 225 additions & 0 deletions src/navigation/ChooseWalletGroup.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
import React from 'react';
import { Box, Separator, Text, useForegroundColor } from '@/design-system';
import { View, Text as NativeText } from 'react-native';
import chroma from 'chroma-js';
import { useInitializeWallet, useWallets } from '@/hooks';
import { PROFILES, useExperimentalFlag } from '@/config';
import { useDispatch } from 'react-redux';
import Routes from '@/navigation/routesNames';
import { useNavigation } from './Navigation';
import WalletBackupTypes from '@/helpers/walletBackupTypes';
import WalletTypes from '@/helpers/walletTypes';
import { backupUserDataIntoCloud } from '@/handlers/cloudBackup';
import { logger, RainbowError } from '@/logger';
import { createAccountForWallet, walletsLoadState } from '@/redux/wallets';
import { createWallet, RainbowAccount, RainbowWallet } from '@/model/wallet';
import { ButtonPressAnimation } from '@/components/animations';
import { formatAddressForDisplay } from '@/utils/abbreviations';
import { ImgixImage } from '@/components/images';
import { useTheme } from '@/theme';
import { removeFirstEmojiFromString, returnStringFirstEmoji } from '@/helpers/emojiHandler';
import { profileUtils } from '@/utils';
import * as i18n from '@/languages';
import showWalletErrorAlert from '@/helpers/support';

function NewWalletGroup() {
const blue = useForegroundColor('blue');

const { navigate } = useNavigation();
const profilesEnabled = useExperimentalFlag(PROFILES);
const dispatch = useDispatch();
const initializeWallet = useInitializeWallet();

const onNewWallet = () => {
navigate(Routes.WALLET_SCREEN);
navigate(Routes.MODAL_SCREEN, {
actionType: 'Create',
asset: [],
isNewProfile: true,
onCloseModal: async (args: { name: string; color: number }) => {
if (!args) return;
try {
const { name, color } = args;
await createWallet({ color, name });
await dispatch(walletsLoadState(profilesEnabled));
// @ts-ignore
await initializeWallet();
} catch (error) {
logger.error(new RainbowError('[AddWalletSheet]: Error while trying to add account'), { error });
}
},
profile: { color: null, name: `` },
type: 'wallet_profile',
});
};

return (
<ButtonPressAnimation onPress={onNewWallet} scaleTo={0.95} style={{ flexDirection: 'row', alignItems: 'center', gap: 10 }}>
<View
style={[
{ height: 36, width: 36 },
{ borderRadius: 9, borderColor: chroma(blue).alpha(0.2).hex(), borderWidth: 2, borderStyle: 'dashed' },
{ alignItems: 'center', justifyContent: 'center' },
]}
>
<Text color="blue" size="icon 14px" weight="heavy">
􀅼
</Text>
</View>
<View style={{ gap: 8 }}>
<Text color="label" size="15pt" weight="semibold">
{i18n.t(i18n.l.wallet.new.new_wallet_group.title)}
</Text>
<Text color="labelQuaternary" size="13pt" weight="bold">
{i18n.t(i18n.l.wallet.new.new_wallet_group.description)}
</Text>
</View>
</ButtonPressAnimation>
);
}

function AccountAvatar({ account, size }: { account: RainbowAccount; size: number }) {
const { colors } = useTheme();

if (account.image) {
return <ImgixImage source={{ uri: account.image }} style={{ height: size, width: size, borderRadius: size / 2 }} />;
}

const backgroundColor = colors.avatarBackgrounds[account.color];
const emoji = returnStringFirstEmoji(account.label) || profileUtils.addressHashedEmoji(account.address);

return (
<View
style={[
{ backgroundColor, height: size, width: size, borderRadius: size / 2 },
{ alignItems: 'center', justifyContent: 'center' },
]}
>
<NativeText style={{ fontSize: size / 2, textAlign: 'center' }}>{emoji}</NativeText>
</View>
);
}

function WalletGroup({ wallet }: { wallet: RainbowWallet }) {
const separatorSecondary = useForegroundColor('separatorSecondary');

const accounts = wallet.addresses;

const { navigate } = useNavigation();
const dispatch = useDispatch();
const initializeWallet = useInitializeWallet();

const onAddToGroup = () => {
navigate(Routes.WALLET_SCREEN);
navigate(Routes.MODAL_SCREEN, {
actionType: 'Create',
asset: [],
isNewProfile: true,
onCloseModal: async (args: { name: string; color: number }) => {
if (!args) return;
try {
const { name, color } = args;
if (wallet.damaged) throw new Error('Wallet is damaged');
const newWallets = await dispatch(createAccountForWallet(wallet.id, color, name));
// @ts-ignore
await initializeWallet();
// If this wallet was previously backed up to the cloud
// We need to update userData backup so it can be restored too
if (wallet.backedUp && wallet.backupType === WalletBackupTypes.cloud) {
try {
await backupUserDataIntoCloud({ wallets: newWallets });
} catch (error) {
logger.error(new RainbowError('[AddWalletSheet]: Updating wallet userdata failed after new account creation'), { error });
throw error;
}
}
} catch (e) {
logger.error(new RainbowError('[AddWalletSheet]: Error while trying to add account'), {
error: e,
});
showWalletErrorAlert();
}
},
profile: { color: null, name: `` },
type: 'wallet_profile',
});
};

return (
<ButtonPressAnimation onPress={onAddToGroup} scaleTo={0.95} style={{ flexDirection: 'row', alignItems: 'center', gap: 10 }}>
<View
style={[
{ height: 40, width: 40, gap: 2, padding: 5 },
{ borderRadius: 10, backgroundColor: separatorSecondary },
{ flexWrap: 'wrap', flexDirection: 'row' },
]}
>
{accounts.map(account => (
<AccountAvatar key={account.address} account={account} size={14} />
))}
</View>
<View style={{ gap: 8 }}>
<Text color="label" size="15pt" weight="semibold">
{removeFirstEmojiFromString(wallet.name)}
</Text>
<View style={{ flexDirection: 'row', alignItems: 'center', gap: 5 }}>
<Text color="labelQuaternary" size="13pt" weight="bold">
{accounts[0].ens || formatAddressForDisplay(accounts[0].address, 4, 4)}
</Text>
{accounts.length > 1 && (
<View
style={[
{ height: 16, paddingHorizontal: 3.5, justifyContent: 'center', marginVertical: -2 },
{ borderColor: chroma(separatorSecondary).alpha(0.04).hex(), borderWidth: 1, borderRadius: 6 },
{ backgroundColor: separatorSecondary },
]}
>
<Text color="labelQuaternary" size="11pt" weight="bold">
{`+${accounts.length - 1}`}
</Text>
</View>
)}
</View>
</View>
</ButtonPressAnimation>
);
}

export function ChooseWalletGroup() {
const { wallets } = useWallets();

if (!wallets) return;

const groups = Object.values(wallets).filter(wallet => wallet.type === WalletTypes.mnemonic);

return (
<Box
height="full"
width="full"
background="surfaceSecondary"
style={{ paddingHorizontal: 24, paddingTop: 72, gap: 20, alignItems: 'center' }}
>
<Text color="label" size="22pt" weight="heavy">
{i18n.t(i18n.l.wallet.new.choose_wallet_group.title)}
</Text>
<Text color="labelQuaternary" size="15pt" weight="semibold" align="center">
{i18n.t(i18n.l.wallet.new.choose_wallet_group.description)}
</Text>
<Box
background="surfaceSecondaryElevated"
// shadow="12px" // TODO: adding shadow clips height (?)
borderColor="buttonStroke"
borderRadius={32}
borderWidth={1}
width="full"
style={{ padding: 20, gap: 16 }}
>
<NewWalletGroup />
<Separator color={'separatorTertiary'} />
{groups.map(wallet => (
<WalletGroup key={wallet.id} wallet={wallet} />
))}
</Box>
</Box>
);
}
1 change: 1 addition & 0 deletions src/navigation/routesNames.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const Routes = {
ADD_CASH_SCREEN_NAVIGATOR: 'AddCashSheetNavigator',
ADD_CASH_SHEET: 'AddCashSheet',
ADD_WALLET_NAVIGATOR: 'AddWalletNavigator',
CHOOSE_WALLET_GROUP: 'ChooseWalletGroup',
ADD_WALLET_SHEET: 'AddWalletSheet',
APP_ICON_UNLOCK_SHEET: 'AppIconUnlockSheet',
AVATAR_BUILDER: 'AvatarBuilder',
Expand Down
Loading

0 comments on commit 48bcd19

Please sign in to comment.