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

Optimization of mobile startup time #31776

Merged
merged 33 commits into from
Nov 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
a19fcb2
Merge branch 'main' of https://github.com/Expensify/App
perunt Oct 5, 2023
78ef9ae
Merge branch 'main' of https://github.com/Expensify/App
perunt Oct 10, 2023
3b0858a
Merge branch 'main' of https://github.com/Expensify/App
perunt Oct 24, 2023
e28a632
Merge branch 'main' of https://github.com/Expensify/App
perunt Oct 25, 2023
9cc08a0
Merge branch 'main' of https://github.com/Expensify/App
perunt Oct 26, 2023
6f5fcf4
Merge branch 'main' of https://github.com/Expensify/App
perunt Nov 3, 2023
cfb5b6a
Merge branch 'main' of https://github.com/Expensify/App
perunt Nov 14, 2023
bc1c7e0
Merge branch 'main' of https://github.com/Expensify/App into perunt/s…
perunt Nov 17, 2023
bffe6f7
Merge branch 'main' of https://github.com/Expensify/App into perunt/s…
perunt Nov 19, 2023
4e7f09a
add lazy imports for AuthScreens
perunt Nov 23, 2023
1c75def
Merge branch 'main' of https://github.com/Expensify/App into perunt/s…
perunt Nov 23, 2023
9a958eb
return RightModalNavigator
perunt Nov 23, 2023
b3d0a63
export SupportedLanguage
perunt Nov 23, 2023
dad435b
lazy import of emojisTrie
perunt Nov 23, 2023
fa945da
lazy BankIcons
perunt Nov 23, 2023
a83117b
add BankName type
perunt Nov 23, 2023
e962db8
fix warning
perunt Nov 23, 2023
1e9d3af
clean
perunt Nov 23, 2023
33c787d
update types
perunt Nov 24, 2023
f72c49c
create Bank type
perunt Nov 24, 2023
61a6701
clean BankIcon component
perunt Nov 24, 2023
b87507a
add BANK_NAMES const
perunt Nov 24, 2023
9f2c4ef
spaces
perunt Nov 24, 2023
1108301
prettier
perunt Nov 24, 2023
706dd00
fix typo
perunt Nov 27, 2023
8141e50
add comments
perunt Nov 27, 2023
c35d737
Merge branch 'main' of https://github.com/Expensify/App into perunt/s…
perunt Nov 27, 2023
25f5b00
Merge branch 'main' of https://github.com/Expensify/App into perunt/s…
perunt Nov 30, 2023
c034e71
fix getBankIcon type after merge
perunt Nov 30, 2023
a0ab476
fix imports
perunt Nov 30, 2023
6166f2b
Merge branch 'main' of https://github.com/Expensify/App into perunt/s…
perunt Nov 30, 2023
cdfb6d7
change the order of imports
perunt Nov 30, 2023
e6d7779
Merge branch 'main' of https://github.com/Expensify/App into perunt/s…
perunt Nov 30, 2023
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
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);
}
perunt marked this conversation as resolved.
Show resolved Hide resolved
}

// 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;
Copy link
Contributor

Choose a reason for hiding this comment

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

Same question here, does it mean that emojisTrie will be imported each time replaceEmojis is called?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If we do not change the required path, it will return the same reference cached in the first load. At least, that's how I understand this after additional research and testing.

Copy link
Contributor

Choose a reason for hiding this comment

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

That's cool, thanks!


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
Loading