Skip to content

Commit

Permalink
Merge pull request Expensify#31776 from margelo/perunt/startup-profiling
Browse files Browse the repository at this point in the history
Optimization of mobile startup time
  • Loading branch information
johnmlee101 authored Nov 30, 2023
2 parents b7f71ca + e6d7779 commit 56a368b
Show file tree
Hide file tree
Showing 8 changed files with 149 additions and 136 deletions.
26 changes: 26 additions & 0 deletions src/CONST.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2852,6 +2852,32 @@ const CONST = {
RUNS: 20,
},

/**
* Bank account names
*/
BANK_NAMES: {
EXPENSIFY: 'expensify',
AMERICAN_EXPRESS: 'americanexpress',
BANK_OF_AMERICA: 'bank of america',
BB_T: 'bbt',
CAPITAL_ONE: 'capital one',
CHASE: 'chase',
CHARLES_SCHWAB: 'charles schwab',
CITIBANK: 'citibank',
CITIZENS_BANK: 'citizens bank',
DISCOVER: 'discover',
FIDELITY: 'fidelity',
GENERIC_BANK: 'generic bank',
HUNTINGTON_BANK: 'huntington bank',
NAVY_FEDERAL_CREDIT_UNION: 'navy federal credit union',
PNC: 'pnc',
REGIONS_BANK: 'regions bank',
SUNTRUST: 'suntrust',
TD_BANK: 'td bank',
US_BANK: 'us bank',
USAA: 'usaa',
},

/**
* Constants for maxToRenderPerBatch parameter that is used for FlatList or SectionList. This controls the amount of items rendered per batch, which is the next chunk of items rendered on every scroll.
*/
Expand Down
219 changes: 90 additions & 129 deletions src/components/Icon/BankIcons.ts
Original file line number Diff line number Diff line change
@@ -1,158 +1,117 @@
import {CSSProperties} from 'react';
import {ViewStyle} from 'react-native';
import {SvgProps} from 'react-native-svg';
import AmericanExpress from '@assets/images/bankicons/american-express.svg';
import BankOfAmerica from '@assets/images/bankicons/bank-of-america.svg';
import BB_T from '@assets/images/bankicons/bb-t.svg';
import CapitalOne from '@assets/images/bankicons/capital-one.svg';
import CharlesSchwab from '@assets/images/bankicons/charles-schwab.svg';
import Chase from '@assets/images/bankicons/chase.svg';
import CitiBank from '@assets/images/bankicons/citibank.svg';
import CitizensBank from '@assets/images/bankicons/citizens-bank.svg';
import Discover from '@assets/images/bankicons/discover.svg';
import Fidelity from '@assets/images/bankicons/fidelity.svg';
import GenericBank from '@assets/images/bankicons/generic-bank-account.svg';
import HuntingtonBank from '@assets/images/bankicons/huntington-bank.svg';
import NavyFederalCreditUnion from '@assets/images/bankicons/navy-federal-credit-union.svg';
import PNC from '@assets/images/bankicons/pnc.svg';
import RegionsBank from '@assets/images/bankicons/regions-bank.svg';
import SunTrust from '@assets/images/bankicons/suntrust.svg';
import TdBank from '@assets/images/bankicons/td-bank.svg';
import USBank from '@assets/images/bankicons/us-bank.svg';
import USAA from '@assets/images/bankicons/usaa.svg';
// Card Icons
import AmericanExpressCard from '@assets/images/cardicons/american-express.svg';
import BankOfAmericaCard from '@assets/images/cardicons/bank-of-america.svg';
import BB_TCard from '@assets/images/cardicons/bb-t.svg';
import CapitalOneCard from '@assets/images/cardicons/capital-one.svg';
import CharlesSchwabCard from '@assets/images/cardicons/charles-schwab.svg';
import ChaseCard from '@assets/images/cardicons/chase.svg';
import CitiBankCard from '@assets/images/cardicons/citibank.svg';
import CitizensBankCard from '@assets/images/cardicons/citizens.svg';
import DiscoverCard from '@assets/images/cardicons/discover.svg';
import ExpensifyCardImage from '@assets/images/cardicons/expensify-card-dark.svg';
import FidelityCard from '@assets/images/cardicons/fidelity.svg';
import GenericBankCard from '@assets/images/cardicons/generic-bank-card.svg';
import HuntingtonBankCard from '@assets/images/cardicons/huntington-bank.svg';
import NavyFederalCreditUnionCard from '@assets/images/cardicons/navy-federal-credit-union.svg';
import PNCCard from '@assets/images/cardicons/pnc.svg';
import RegionsBankCard from '@assets/images/cardicons/regions-bank.svg';
import SunTrustCard from '@assets/images/cardicons/suntrust.svg';
import TdBankCard from '@assets/images/cardicons/td-bank.svg';
import USBankCard from '@assets/images/cardicons/us-bank.svg';
import USAACard from '@assets/images/cardicons/usaa.svg';
import {ThemeStyles} from '@styles/styles';
import variables from '@styles/variables';

type BankIcon = {
icon: React.FC<SvgProps>;
iconSize?: number;
iconHeight?: number;
iconWidth?: number;
iconStyles?: Array<ViewStyle | CSSProperties>;
};
import CONST from '@src/CONST';
import {BankIcon, BankName, BankNameKey} from '@src/types/onyx/Bank';

type BankIconParams = {
themeStyles: ThemeStyles;
bankName?: string;
bankName?: BankName;
isCard?: boolean;
};

/**
* Returns matching asset icon for bankName
*/

function getAssetIcon(bankName: string, isCard: boolean): React.FC<SvgProps> {
if (bankName.includes('expensify')) {
return ExpensifyCardImage;
}

if (bankName.includes('americanexpress')) {
return isCard ? AmericanExpressCard : AmericanExpress;
}

if (bankName.includes('bank of america') || bankName.includes('bankofamerica')) {
return isCard ? BankOfAmericaCard : BankOfAmerica;
}

if (bankName.startsWith('bbt')) {
return isCard ? BB_TCard : BB_T;
}

if (bankName.startsWith('capital one') || bankName.includes('capitalone')) {
return isCard ? CapitalOneCard : CapitalOne;
}

if (bankName.startsWith('chase') || bankName.includes('chase')) {
return isCard ? ChaseCard : Chase;
}

if (bankName.includes('charles schwab') || bankName.includes('charlesschwab')) {
return isCard ? CharlesSchwabCard : CharlesSchwab;
}

if (bankName.startsWith('citibank') || bankName.includes('citibank')) {
return isCard ? CitiBankCard : CitiBank;
}

if (bankName.startsWith('citizens bank') || bankName.includes('citizensbank')) {
return isCard ? CitizensBankCard : CitizensBank;
}

if (bankName.startsWith('discover ') || bankName.includes('discover.') || bankName === 'discover') {
return isCard ? DiscoverCard : Discover;
}

if (bankName.startsWith('fidelity')) {
return isCard ? FidelityCard : Fidelity;
}

if (bankName.startsWith('huntington bank') || bankName.includes('huntingtonnational') || bankName.includes('huntington national')) {
return isCard ? HuntingtonBankCard : HuntingtonBank;
}

if (bankName.startsWith('navy federal credit union') || bankName.includes('navy federal credit union')) {
return isCard ? NavyFederalCreditUnionCard : NavyFederalCreditUnion;
}

if (bankName.startsWith('pnc') || bankName.includes('pnc')) {
return isCard ? PNCCard : PNC;
}

if (bankName.startsWith('regions bank') || bankName.includes('regionsbank')) {
return isCard ? RegionsBankCard : RegionsBank;
}

if (bankName.startsWith('suntrust') || bankName.includes('suntrust')) {
return isCard ? SunTrustCard : SunTrust;
}

if (bankName.startsWith('td bank') || bankName.startsWith('tdbank') || bankName.includes('tdbank')) {
return isCard ? TdBankCard : TdBank;
}

if (bankName.startsWith('us bank') || bankName.startsWith('usbank')) {
return isCard ? USBankCard : USBank;
}

if (bankName.includes('usaa')) {
return isCard ? USAACard : USAA;
}
function getAssetIcon(bankNameKey: BankNameKey, isCard: boolean): React.FC<SvgProps> {
const bankValue = CONST.BANK_NAMES[bankNameKey];

// This maps bank names to their respective icon paths.
// The purpose is to avoid importing these at the app startup stage.
// Depending on whether 'isCard' is true, it selects either a card icon or a bank icon.
const iconMappings = {
[CONST.BANK_NAMES.EXPENSIFY]: isCard
? (require('@assets/images/cardicons/expensify-card-dark.svg').default as React.FC<SvgProps>)
: (require('@assets/images/bankicons/expensify.svg').default as React.FC<SvgProps>),
[CONST.BANK_NAMES.AMERICAN_EXPRESS]: isCard
? (require('@assets/images/cardicons/american-express.svg').default as React.FC<SvgProps>)
: (require('@assets/images/bankicons/american-express.svg').default as React.FC<SvgProps>),
[CONST.BANK_NAMES.BANK_OF_AMERICA]: isCard
? (require('@assets/images/cardicons/bank-of-america.svg').default as React.FC<SvgProps>)
: (require('@assets/images/bankicons/bank-of-america.svg').default as React.FC<SvgProps>),
[CONST.BANK_NAMES.BB_T]: isCard
? (require('@assets/images/cardicons/bb-t.svg').default as React.FC<SvgProps>)
: (require('@assets/images/bankicons/bb-t.svg').default as React.FC<SvgProps>),
[CONST.BANK_NAMES.CAPITAL_ONE]: isCard
? (require('@assets/images/cardicons/capital-one.svg').default as React.FC<SvgProps>)
: (require('@assets/images/bankicons/capital-one.svg').default as React.FC<SvgProps>),
[CONST.BANK_NAMES.CHASE]: isCard
? (require('@assets/images/cardicons/chase.svg').default as React.FC<SvgProps>)
: (require('@assets/images/bankicons/chase.svg').default as React.FC<SvgProps>),
[CONST.BANK_NAMES.CHARLES_SCHWAB]: isCard
? (require('@assets/images/cardicons/charles-schwab.svg').default as React.FC<SvgProps>)
: (require('@assets/images/bankicons/charles-schwab.svg').default as React.FC<SvgProps>),
[CONST.BANK_NAMES.CITIBANK]: isCard
? (require('@assets/images/cardicons/citibank.svg').default as React.FC<SvgProps>)
: (require('@assets/images/bankicons/citibank.svg').default as React.FC<SvgProps>),
[CONST.BANK_NAMES.CITIZENS_BANK]: isCard
? (require('@assets/images/cardicons/citizens.svg').default as React.FC<SvgProps>)
: (require('@assets/images/bankicons/citizens-bank.svg').default as React.FC<SvgProps>),
[CONST.BANK_NAMES.DISCOVER]: isCard
? (require('@assets/images/cardicons/discover.svg').default as React.FC<SvgProps>)
: (require('@assets/images/bankicons/discover.svg').default as React.FC<SvgProps>),
[CONST.BANK_NAMES.FIDELITY]: isCard
? (require('@assets/images/cardicons/fidelity.svg').default as React.FC<SvgProps>)
: (require('@assets/images/bankicons/fidelity.svg').default as React.FC<SvgProps>),
[CONST.BANK_NAMES.GENERIC_BANK]: isCard
? (require('@assets/images/cardicons/generic-bank-card.svg').default as React.FC<SvgProps>)
: (require('@assets/images/bankicons/generic-bank-account.svg').default as React.FC<SvgProps>),
[CONST.BANK_NAMES.HUNTINGTON_BANK]: isCard
? (require('@assets/images/cardicons/huntington-bank.svg').default as React.FC<SvgProps>)
: (require('@assets/images/bankicons/huntington-bank.svg').default as React.FC<SvgProps>),
[CONST.BANK_NAMES.NAVY_FEDERAL_CREDIT_UNION]: isCard
? (require('@assets/images/cardicons/navy-federal-credit-union.svg').default as React.FC<SvgProps>)
: (require('@assets/images/bankicons/navy-federal-credit-union.svg').default as React.FC<SvgProps>),
[CONST.BANK_NAMES.PNC]: isCard
? (require('@assets/images/cardicons/pnc.svg').default as React.FC<SvgProps>)
: (require('@assets/images/bankicons/pnc.svg').default as React.FC<SvgProps>),
[CONST.BANK_NAMES.REGIONS_BANK]: isCard
? (require('@assets/images/cardicons/regions-bank.svg').default as React.FC<SvgProps>)
: (require('@assets/images/bankicons/regions-bank.svg').default as React.FC<SvgProps>),
[CONST.BANK_NAMES.SUNTRUST]: isCard
? (require('@assets/images/cardicons/suntrust.svg').default as React.FC<SvgProps>)
: (require('@assets/images/bankicons/suntrust.svg').default as React.FC<SvgProps>),
[CONST.BANK_NAMES.TD_BANK]: isCard
? (require('@assets/images/cardicons/td-bank.svg').default as React.FC<SvgProps>)
: (require('@assets/images/bankicons/td-bank.svg').default as React.FC<SvgProps>),
[CONST.BANK_NAMES.US_BANK]: isCard
? (require('@assets/images/cardicons/us-bank.svg').default as React.FC<SvgProps>)
: (require('@assets/images/bankicons/us-bank.svg').default as React.FC<SvgProps>),
[CONST.BANK_NAMES.USAA]: isCard
? (require('@assets/images/cardicons/usaa.svg').default as React.FC<SvgProps>)
: (require('@assets/images/bankicons/usaa.svg').default as React.FC<SvgProps>),
} as const;

// Fallback to generic bank/card icon
const iconModule =
iconMappings[bankValue] ||
(isCard
? (require('@assets/images/cardicons/generic-bank-card.svg').default as React.FC<SvgProps>)
: (require('@assets/images/bankicons/generic-bank-account.svg').default as React.FC<SvgProps>));
return iconModule;
}

return isCard ? GenericBankCard : GenericBank;
function getBankNameKey(bankName: string): BankNameKey {
const bank = Object.entries(CONST.BANK_NAMES).find(([, value]) => value?.toLowerCase() === bankName);
return (bank?.[0] as BankNameKey) ?? '';
}

/**
* Returns Bank Icon Object that matches to existing bank icons or default icons
*/

export default function getBankIcon({themeStyles, bankName, isCard = false}: BankIconParams): BankIcon {
const bankIcon: BankIcon = {
icon: isCard ? GenericBankCard : GenericBank,
};

if (bankName) {
bankIcon.icon = getAssetIcon(bankName.toLowerCase(), isCard);
const bankNameKey = getBankNameKey(bankName.toLowerCase());

if (bankNameKey && Object.keys(CONST.BANK_NAMES).includes(bankNameKey)) {
bankIcon.icon = getAssetIcon(bankNameKey, isCard);
}
}

// For default Credit Card icon the icon size should not be set.
Expand All @@ -167,3 +126,5 @@ export default function getBankIcon({themeStyles, bankName, isCard = false}: Ban

return bankIcon;
}

export type {BankName};
2 changes: 1 addition & 1 deletion src/libs/EmojiTrie.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,4 +128,4 @@ const emojiTrie: EmojiTrie = supportedLanguages.reduce((prev, cur) => ({...prev,
Timing.end(CONST.TIMING.TRIE_INITIALIZATION);

export default emojiTrie;
export type {SimpleEmoji};
export type {SimpleEmoji, SupportedLanguage};
10 changes: 8 additions & 2 deletions src/libs/EmojiUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {Emoji, HeaderEmoji, PickerEmojis} from '@assets/emojis/types';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import {FrequentlyUsedEmoji} from '@src/types/onyx';
import emojisTrie from './EmojiTrie';
import {SupportedLanguage} from './EmojiTrie';

type HeaderIndice = {code: string; index: number; icon: React.FC<SvgProps>};
type EmojiSpacer = {code: string; spacer: boolean};
Expand Down Expand Up @@ -322,6 +322,9 @@ function getAddedEmojis(currentEmojis: Emoji[], formerEmojis: Emoji[]): Emoji[]
* If we're on mobile, we also add a space after the emoji granted there's no text after it.
*/
function replaceEmojis(text: string, preferredSkinTone = CONST.EMOJI_DEFAULT_SKIN_TONE, lang: 'en' | 'es' = CONST.LOCALES.DEFAULT): ReplacedEmoji {
// emojisTrie is importing the emoji JSON file on the app starting and we want to avoid it
const emojisTrie = require('./EmojiTrie').default;

const trie = emojisTrie[lang];
if (!trie) {
return {text, emojis: []};
Expand Down Expand Up @@ -396,7 +399,10 @@ function replaceAndExtractEmojis(text: string, preferredSkinTone = CONST.EMOJI_D
* Suggest emojis when typing emojis prefix after colon
* @param [limit] - matching emojis limit
*/
function suggestEmojis(text: string, lang: keyof typeof emojisTrie, limit = CONST.AUTO_COMPLETE_SUGGESTER.MAX_AMOUNT_OF_SUGGESTIONS): Emoji[] | undefined {
function suggestEmojis(text: string, lang: keyof SupportedLanguage, limit = CONST.AUTO_COMPLETE_SUGGESTER.MAX_AMOUNT_OF_SUGGESTIONS): Emoji[] | undefined {
// emojisTrie is importing the emoji JSON file on the app starting and we want to avoid it
const emojisTrie = require('./EmojiTrie').default;

const trie = emojisTrie[lang];
if (!trie) {
return [];
Expand Down
4 changes: 2 additions & 2 deletions src/libs/PaymentUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ function formatPaymentMethods(bankAccountList: Record<string, BankAccount>, fund
}

const {icon, iconSize, iconHeight, iconWidth, iconStyles} = getBankIcon({
bankName: bankAccount?.accountData?.additionalData?.bankName ?? '',
bankName: bankAccount?.accountData?.additionalData?.bankName,
isCard: false,
themeStyles,
});
Expand All @@ -66,7 +66,7 @@ function formatPaymentMethods(bankAccountList: Record<string, BankAccount>, fund
});

Object.values(fundList).forEach((card) => {
const {icon, iconSize, iconHeight, iconWidth, iconStyles} = getBankIcon({bankName: card?.accountData?.bank ?? '', isCard: true, themeStyles});
const {icon, iconSize, iconHeight, iconWidth, iconStyles} = getBankIcon({bankName: card?.accountData?.bank, isCard: true, themeStyles});
combinedPaymentMethods.push({
...card,
description: getPaymentMethodDescription(card?.accountType, card.accountData),
Expand Down
3 changes: 2 additions & 1 deletion src/types/onyx/AccountData.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import {BankName} from './Bank';
import * as OnyxCommon from './OnyxCommon';

type AdditionalData = {
isP2PDebitCard?: boolean;
beneficialOwners?: string[];
currency?: string;
bankName?: string;
bankName?: BankName;
fieldsType?: string;
country?: string;
};
Expand Down
18 changes: 18 additions & 0 deletions src/types/onyx/Bank.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import {CSSProperties} from 'react';
import {ViewStyle} from 'react-native';
import {SvgProps} from 'react-native-svg';
import {ValueOf} from 'type-fest';
import CONST from '@src/CONST';

type BankIcon = {
icon: React.FC<SvgProps>;
iconSize?: number;
iconHeight?: number;
iconWidth?: number;
iconStyles?: Array<ViewStyle | CSSProperties>;
};

type BankName = ValueOf<typeof CONST.BANK_NAMES>;
type BankNameKey = keyof typeof CONST.BANK_NAMES;

export type {BankIcon, BankName, BankNameKey};
3 changes: 2 additions & 1 deletion src/types/onyx/Fund.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import CONST from '@src/CONST';
import {BankName} from './Bank';
import * as OnyxCommon from './OnyxCommon';

type AdditionalData = {
Expand All @@ -21,7 +22,7 @@ type AccountData = {
created?: string;
currency?: string;
fundID?: number;
bank?: string;
bank?: BankName;
};

type Fund = {
Expand Down

0 comments on commit 56a368b

Please sign in to comment.