diff --git a/src/CONST.ts b/src/CONST.ts index d813d3e016c2..5751c588ead8 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -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. */ diff --git a/src/components/Icon/BankIcons.ts b/src/components/Icon/BankIcons.ts index fa8ebdf9c3eb..81e9075091c6 100644 --- a/src/components/Icon/BankIcons.ts +++ b/src/components/Icon/BankIcons.ts @@ -1,60 +1,14 @@ -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; - iconSize?: number; - iconHeight?: number; - iconWidth?: number; - iconStyles?: Array; -}; +import CONST from '@src/CONST'; +import {BankIcon, BankName, BankNameKey} from '@src/types/onyx/Bank'; type BankIconParams = { themeStyles: ThemeStyles; - bankName?: string; + bankName?: BankName; isCard?: boolean; }; @@ -62,97 +16,102 @@ type BankIconParams = { * Returns matching asset icon for bankName */ -function getAssetIcon(bankName: string, isCard: boolean): React.FC { - 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 { + 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) + : (require('@assets/images/bankicons/expensify.svg').default as React.FC), + [CONST.BANK_NAMES.AMERICAN_EXPRESS]: isCard + ? (require('@assets/images/cardicons/american-express.svg').default as React.FC) + : (require('@assets/images/bankicons/american-express.svg').default as React.FC), + [CONST.BANK_NAMES.BANK_OF_AMERICA]: isCard + ? (require('@assets/images/cardicons/bank-of-america.svg').default as React.FC) + : (require('@assets/images/bankicons/bank-of-america.svg').default as React.FC), + [CONST.BANK_NAMES.BB_T]: isCard + ? (require('@assets/images/cardicons/bb-t.svg').default as React.FC) + : (require('@assets/images/bankicons/bb-t.svg').default as React.FC), + [CONST.BANK_NAMES.CAPITAL_ONE]: isCard + ? (require('@assets/images/cardicons/capital-one.svg').default as React.FC) + : (require('@assets/images/bankicons/capital-one.svg').default as React.FC), + [CONST.BANK_NAMES.CHASE]: isCard + ? (require('@assets/images/cardicons/chase.svg').default as React.FC) + : (require('@assets/images/bankicons/chase.svg').default as React.FC), + [CONST.BANK_NAMES.CHARLES_SCHWAB]: isCard + ? (require('@assets/images/cardicons/charles-schwab.svg').default as React.FC) + : (require('@assets/images/bankicons/charles-schwab.svg').default as React.FC), + [CONST.BANK_NAMES.CITIBANK]: isCard + ? (require('@assets/images/cardicons/citibank.svg').default as React.FC) + : (require('@assets/images/bankicons/citibank.svg').default as React.FC), + [CONST.BANK_NAMES.CITIZENS_BANK]: isCard + ? (require('@assets/images/cardicons/citizens.svg').default as React.FC) + : (require('@assets/images/bankicons/citizens-bank.svg').default as React.FC), + [CONST.BANK_NAMES.DISCOVER]: isCard + ? (require('@assets/images/cardicons/discover.svg').default as React.FC) + : (require('@assets/images/bankicons/discover.svg').default as React.FC), + [CONST.BANK_NAMES.FIDELITY]: isCard + ? (require('@assets/images/cardicons/fidelity.svg').default as React.FC) + : (require('@assets/images/bankicons/fidelity.svg').default as React.FC), + [CONST.BANK_NAMES.GENERIC_BANK]: isCard + ? (require('@assets/images/cardicons/generic-bank-card.svg').default as React.FC) + : (require('@assets/images/bankicons/generic-bank-account.svg').default as React.FC), + [CONST.BANK_NAMES.HUNTINGTON_BANK]: isCard + ? (require('@assets/images/cardicons/huntington-bank.svg').default as React.FC) + : (require('@assets/images/bankicons/huntington-bank.svg').default as React.FC), + [CONST.BANK_NAMES.NAVY_FEDERAL_CREDIT_UNION]: isCard + ? (require('@assets/images/cardicons/navy-federal-credit-union.svg').default as React.FC) + : (require('@assets/images/bankicons/navy-federal-credit-union.svg').default as React.FC), + [CONST.BANK_NAMES.PNC]: isCard + ? (require('@assets/images/cardicons/pnc.svg').default as React.FC) + : (require('@assets/images/bankicons/pnc.svg').default as React.FC), + [CONST.BANK_NAMES.REGIONS_BANK]: isCard + ? (require('@assets/images/cardicons/regions-bank.svg').default as React.FC) + : (require('@assets/images/bankicons/regions-bank.svg').default as React.FC), + [CONST.BANK_NAMES.SUNTRUST]: isCard + ? (require('@assets/images/cardicons/suntrust.svg').default as React.FC) + : (require('@assets/images/bankicons/suntrust.svg').default as React.FC), + [CONST.BANK_NAMES.TD_BANK]: isCard + ? (require('@assets/images/cardicons/td-bank.svg').default as React.FC) + : (require('@assets/images/bankicons/td-bank.svg').default as React.FC), + [CONST.BANK_NAMES.US_BANK]: isCard + ? (require('@assets/images/cardicons/us-bank.svg').default as React.FC) + : (require('@assets/images/bankicons/us-bank.svg').default as React.FC), + [CONST.BANK_NAMES.USAA]: isCard + ? (require('@assets/images/cardicons/usaa.svg').default as React.FC) + : (require('@assets/images/bankicons/usaa.svg').default as React.FC), + } 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) + : (require('@assets/images/bankicons/generic-bank-account.svg').default as React.FC)); + 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. @@ -167,3 +126,5 @@ export default function getBankIcon({themeStyles, bankName, isCard = false}: Ban return bankIcon; } + +export type {BankName}; diff --git a/src/libs/EmojiTrie.ts b/src/libs/EmojiTrie.ts index a45d1bc45b33..100d24a01546 100644 --- a/src/libs/EmojiTrie.ts +++ b/src/libs/EmojiTrie.ts @@ -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}; diff --git a/src/libs/EmojiUtils.ts b/src/libs/EmojiUtils.ts index 22e84921b1ee..22bfc83218ac 100644 --- a/src/libs/EmojiUtils.ts +++ b/src/libs/EmojiUtils.ts @@ -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}; type EmojiSpacer = {code: string; spacer: boolean}; @@ -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: []}; @@ -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 []; diff --git a/src/libs/PaymentUtils.ts b/src/libs/PaymentUtils.ts index 456cd21c81af..fc2bfb6d83fb 100644 --- a/src/libs/PaymentUtils.ts +++ b/src/libs/PaymentUtils.ts @@ -50,7 +50,7 @@ function formatPaymentMethods(bankAccountList: Record, fund } const {icon, iconSize, iconHeight, iconWidth, iconStyles} = getBankIcon({ - bankName: bankAccount?.accountData?.additionalData?.bankName ?? '', + bankName: bankAccount?.accountData?.additionalData?.bankName, isCard: false, themeStyles, }); @@ -66,7 +66,7 @@ function formatPaymentMethods(bankAccountList: Record, 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), diff --git a/src/types/onyx/AccountData.ts b/src/types/onyx/AccountData.ts index 79484e7886af..601e82cde836 100644 --- a/src/types/onyx/AccountData.ts +++ b/src/types/onyx/AccountData.ts @@ -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; }; diff --git a/src/types/onyx/Bank.ts b/src/types/onyx/Bank.ts new file mode 100644 index 000000000000..b6312e039079 --- /dev/null +++ b/src/types/onyx/Bank.ts @@ -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; + iconSize?: number; + iconHeight?: number; + iconWidth?: number; + iconStyles?: Array; +}; + +type BankName = ValueOf; +type BankNameKey = keyof typeof CONST.BANK_NAMES; + +export type {BankIcon, BankName, BankNameKey}; diff --git a/src/types/onyx/Fund.ts b/src/types/onyx/Fund.ts index 4e6cbc695a8d..82c15c5089d7 100644 --- a/src/types/onyx/Fund.ts +++ b/src/types/onyx/Fund.ts @@ -1,4 +1,5 @@ import CONST from '@src/CONST'; +import {BankName} from './Bank'; import * as OnyxCommon from './OnyxCommon'; type AdditionalData = { @@ -21,7 +22,7 @@ type AccountData = { created?: string; currency?: string; fundID?: number; - bank?: string; + bank?: BankName; }; type Fund = {