diff --git a/android/app/src/main/java/com/expensify/chat/MainApplication.kt b/android/app/src/main/java/com/expensify/chat/MainApplication.kt index 5d0948ee3405..46479bc7cf43 100644 --- a/android/app/src/main/java/com/expensify/chat/MainApplication.kt +++ b/android/app/src/main/java/com/expensify/chat/MainApplication.kt @@ -63,10 +63,10 @@ class MainApplication : MultiDexApplication(), ReactApplication { override fun onCreate() { super.onCreate() + ReactFontManager.getInstance().addCustomFont(this, "Custom Emoji Font", R.font.custom_emoji_font) ReactFontManager.getInstance().addCustomFont(this, "Expensify New Kansas", R.font.expensify_new_kansas) ReactFontManager.getInstance().addCustomFont(this, "Expensify Neue", R.font.expensify_neue) ReactFontManager.getInstance().addCustomFont(this, "Expensify Mono", R.font.expensify_mono) - RNPerformance.getInstance().mark("appCreationStart", false); if (isOnfidoProcess()) { diff --git a/android/app/src/main/res/font/custom_emoji_font.xml b/android/app/src/main/res/font/custom_emoji_font.xml new file mode 100644 index 000000000000..67499bdc92b5 --- /dev/null +++ b/android/app/src/main/res/font/custom_emoji_font.xml @@ -0,0 +1,4 @@ + + + + diff --git a/android/app/src/main/res/font/custom_emoji_native_font.ttf b/android/app/src/main/res/font/custom_emoji_native_font.ttf new file mode 100644 index 000000000000..856eabdb9033 Binary files /dev/null and b/android/app/src/main/res/font/custom_emoji_native_font.ttf differ diff --git a/android/link-assets-manifest.json b/android/link-assets-manifest.json index 9cf517a7fab4..1d7e3e5dc7e3 100644 --- a/android/link-assets-manifest.json +++ b/android/link-assets-manifest.json @@ -1,6 +1,10 @@ { "migIndex": 2, "data": [ + { + "path": "assets/fonts/native/CustomEmojiNativeFont.ttf", + "sha1": "83acdb6db84b418c51037af51f96ff9c18273a62" + }, { "path": "assets/fonts/native/ExpensifyMono-Bold.otf", "sha1": "d70e12540200613e9e6ac9068bed57e4bf477bfe" diff --git a/assets/css/fonts.css b/assets/css/fonts.css index 7d24eb353189..4fb97cc3d768 100644 --- a/assets/css/fonts.css +++ b/assets/css/fonts.css @@ -73,6 +73,11 @@ src: url('/fonts/seguiemj.ttf'); } +@font-face { + font-family: Custom Emoji Font; + src: url('/fonts/CustomEmojiWebFont.ttf') format('truetype'); +} + * { -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; diff --git a/assets/emojis/common.ts b/assets/emojis/common.ts index 1039249f0ac8..009a42d905ad 100644 --- a/assets/emojis/common.ts +++ b/assets/emojis/common.ts @@ -7,6 +7,7 @@ import TravelAndPlaces from '@assets/images/emojiCategoryIcons/plane.svg'; import AnimalsAndNature from '@assets/images/emojiCategoryIcons/plant.svg'; import Activities from '@assets/images/emojiCategoryIcons/soccer-ball.svg'; import FrequentlyUsed from '@assets/images/history.svg'; +import CONST from '@src/CONST'; import type {HeaderEmoji, PickerEmojis} from './types'; const skinTones = [ @@ -7862,6 +7863,10 @@ const emojis: PickerEmojis = [ name: 'wales', code: '🏴󠁧󠁢󠁷󠁬󠁳󠁿', }, + { + name: 'global_create', + code: CONST.CUSTOM_EMOJIS.GLOBAL_CREATE, + }, ]; const categoryFrequentlyUsed: HeaderEmoji = { diff --git a/assets/emojis/en.ts b/assets/emojis/en.ts index a246d51c41bc..2f07cb9cffc6 100644 --- a/assets/emojis/en.ts +++ b/assets/emojis/en.ts @@ -5613,6 +5613,9 @@ const enEmojis: EmojisList = { '🏴󠁧󠁢󠁷󠁬󠁳󠁿': { keywords: ['flag'], }, + '\uE100': { + keywords: ['fab', 'floating', 'action', 'button', 'green', 'plus'], + }, }; export default enEmojis; diff --git a/assets/emojis/es.ts b/assets/emojis/es.ts index 67e97caf2121..b33d41348929 100644 --- a/assets/emojis/es.ts +++ b/assets/emojis/es.ts @@ -7483,6 +7483,10 @@ const esEmojis: EmojisList = { name: 'gales', keywords: ['bandera', 'bandera-gales'], }, + '\uE100': { + name: 'crear-global', + keywords: ['fab', 'flotante', 'acción', 'botón', 'verde', 'más'], + }, }; export default esEmojis; diff --git a/assets/fonts/native/CustomEmojiNativeFont.ttf b/assets/fonts/native/CustomEmojiNativeFont.ttf new file mode 100644 index 000000000000..856eabdb9033 Binary files /dev/null and b/assets/fonts/native/CustomEmojiNativeFont.ttf differ diff --git a/assets/fonts/web/CustomEmojiWebFont.ttf b/assets/fonts/web/CustomEmojiWebFont.ttf new file mode 100644 index 000000000000..87a94dd6abeb Binary files /dev/null and b/assets/fonts/web/CustomEmojiWebFont.ttf differ diff --git a/ios/NewExpensify.xcodeproj/project.pbxproj b/ios/NewExpensify.xcodeproj/project.pbxproj index d2a02f32a559..3f8f534b9450 100644 --- a/ios/NewExpensify.xcodeproj/project.pbxproj +++ b/ios/NewExpensify.xcodeproj/project.pbxproj @@ -48,6 +48,7 @@ ED222ED90E074A5481A854FA /* ExpensifyNeue-BoldItalic.otf in Resources */ = {isa = PBXBuildFile; fileRef = 8B28D84EF339436DBD42A203 /* ExpensifyNeue-BoldItalic.otf */; }; F0C450EA2705020500FD2970 /* colors.json in Resources */ = {isa = PBXBuildFile; fileRef = F0C450E92705020500FD2970 /* colors.json */; }; FF941A8D48F849269AB85C9A /* ExpensifyNewKansas-Medium.otf in Resources */ = {isa = PBXBuildFile; fileRef = 44BF435285B94E5B95F90994 /* ExpensifyNewKansas-Medium.otf */; }; + 59164B2F48344A53975791A9 /* CustomEmojiNativeFont.ttf in Resources */ = {isa = PBXBuildFile; fileRef = B42BBCC5FB8E4E40B1A9202C /* CustomEmojiNativeFont.ttf */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -158,6 +159,7 @@ F0C450E92705020500FD2970 /* colors.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; name = colors.json; path = ../colors.json; sourceTree = ""; }; F4F8A052A22040339996324B /* ExpensifyNeue-Regular.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "ExpensifyNeue-Regular.otf"; path = "../assets/fonts/native/ExpensifyNeue-Regular.otf"; sourceTree = ""; }; F8839E9820F4C312BD1C9339 /* Pods-NewExpensify.releasedevelopment.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NewExpensify.releasedevelopment.xcconfig"; path = "Target Support Files/Pods-NewExpensify/Pods-NewExpensify.releasedevelopment.xcconfig"; sourceTree = ""; }; + B42BBCC5FB8E4E40B1A9202C /* CustomEmojiNativeFont.ttf */ = {isa = PBXFileReference; name = "CustomEmojiNativeFont.ttf"; path = "../assets/fonts/native/CustomEmojiNativeFont.ttf"; sourceTree = ""; fileEncoding = undefined; lastKnownFileType = unknown; explicitFileType = undefined; includeInIndex = 0; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -319,6 +321,7 @@ 8B28D84EF339436DBD42A203 /* ExpensifyNeue-BoldItalic.otf */, BF6A4C5167244B9FB8E4D4E3 /* ExpensifyNeue-Italic.otf */, F4F8A052A22040339996324B /* ExpensifyNeue-Regular.otf */, + B42BBCC5FB8E4E40B1A9202C /* CustomEmojiNativeFont.ttf */, ); name = Resources; sourceTree = ""; @@ -491,6 +494,7 @@ D27CE6B77196EF3EF450EEAC /* PrivacyInfo.xcprivacy in Resources */, 524F95D57E75496EBD14B0AA /* ExpensifyMono-BoldItalic.otf in Resources */, 0F749C2B3B8F4562B816DEAB /* BuildFile in Resources */, + 59164B2F48344A53975791A9 /* CustomEmojiNativeFont.ttf in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/ios/NewExpensify/Info.plist b/ios/NewExpensify/Info.plist index f4dd5bda3ea2..90856aba0304 100644 --- a/ios/NewExpensify/Info.plist +++ b/ios/NewExpensify/Info.plist @@ -99,6 +99,7 @@ ExpensifyNeue-BoldItalic.otf ExpensifyNeue-Italic.otf ExpensifyNeue-Regular.otf + CustomEmojiNativeFont.ttf UIBackgroundModes diff --git a/ios/link-assets-manifest.json b/ios/link-assets-manifest.json index 9cf517a7fab4..1d7e3e5dc7e3 100644 --- a/ios/link-assets-manifest.json +++ b/ios/link-assets-manifest.json @@ -1,6 +1,10 @@ { "migIndex": 2, "data": [ + { + "path": "assets/fonts/native/CustomEmojiNativeFont.ttf", + "sha1": "83acdb6db84b418c51037af51f96ff9c18273a62" + }, { "path": "assets/fonts/native/ExpensifyMono-Bold.otf", "sha1": "d70e12540200613e9e6ac9068bed57e4bf477bfe" diff --git a/package-lock.json b/package-lock.json index 6b71500ec3fc..2f91d6f816d8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,7 +17,7 @@ "@expensify/nitro-utils": "file:./modules/ExpensifyNitroUtils", "@expensify/react-native-background-task": "file:./modules/background-task", "@expensify/react-native-hybrid-app": "file:./modules/hybrid-app", - "@expensify/react-native-live-markdown": "0.1.288", + "@expensify/react-native-live-markdown": "0.1.289", "@expensify/react-native-wallet": "^0.1.5", "@expo/metro-runtime": "^5.0.4", "@firebase/app": "^0.10.10", @@ -4372,9 +4372,9 @@ "link": true }, "node_modules/@expensify/react-native-live-markdown": { - "version": "0.1.288", - "resolved": "https://registry.npmjs.org/@expensify/react-native-live-markdown/-/react-native-live-markdown-0.1.288.tgz", - "integrity": "sha512-TZGr6sAfDonaifbqzGFfZ4uYx6RrvHtbwzf4MlPGOuCdkBiNAXWBIbou6RJm4ILoM3l0YMY317UxhpZVssbGCg==", + "version": "0.1.289", + "resolved": "https://registry.npmjs.org/@expensify/react-native-live-markdown/-/react-native-live-markdown-0.1.289.tgz", + "integrity": "sha512-U+QHKDIEXDGvvk+zKthKncc+hrVD/9fdBBzjtV0rvA4aegU9plFkWJNkwfscVSAKzQCyiPSHaeSqa/ZSFjv68g==", "license": "MIT", "workspaces": [ "./example", diff --git a/package.json b/package.json index 0aca78525cf0..a30380284fc7 100644 --- a/package.json +++ b/package.json @@ -86,7 +86,7 @@ "@expensify/nitro-utils": "file:./modules/ExpensifyNitroUtils", "@expensify/react-native-background-task": "file:./modules/background-task", "@expensify/react-native-hybrid-app": "file:./modules/hybrid-app", - "@expensify/react-native-live-markdown": "0.1.288", + "@expensify/react-native-live-markdown": "0.1.289", "@expensify/react-native-wallet": "^0.1.5", "@expo/metro-runtime": "^5.0.4", "@firebase/app": "^0.10.10", diff --git a/src/CONST/index.ts b/src/CONST/index.ts index 7ebfb584a859..e99800ec8a4f 100755 --- a/src/CONST/index.ts +++ b/src/CONST/index.ts @@ -1727,6 +1727,10 @@ const CONST = { // Amount of emojis to render ahead at the end of the update cycle EMOJI_DRAW_AMOUNT: 100, + CUSTOM_EMOJIS: { + GLOBAL_CREATE: '\uE100', + }, + INVISIBLE_CODEPOINTS: ['fe0f', '200d', '2066'], UNICODE: { @@ -3429,10 +3433,14 @@ const CONST = { // eslint-disable-next-line max-len, no-misleading-character-class EMOJI: /[\p{Extended_Pictographic}\u200d\u{1f1e6}-\u{1f1ff}\u{1f3fb}-\u{1f3ff}\u{e0020}-\u{e007f}\u20E3\uFE0F]|[#*0-9]\uFE0F?\u20E3/gu, // eslint-disable-next-line max-len, no-misleading-character-class, no-empty-character-class - EMOJIS: /[\p{Extended_Pictographic}](\u200D[\p{Extended_Pictographic}]|[\u{1F3FB}-\u{1F3FF}]|[\u{E0020}-\u{E007F}]|\uFE0F|\u20E3)*|[\u{1F1E6}-\u{1F1FF}]{2}|[#*0-9]\uFE0F?\u20E3/du, + EMOJIS: /[\p{Extended_Pictographic}\uE000-\uF8FF\u{F0000}-\u{FFFFD}\u{100000}-\u{10FFFD}](\u200D[\p{Extended_Pictographic}\uE000-\uF8FF\u{F0000}-\u{FFFFD}\u{100000}-\u{10FFFD}]|[\u{1F3FB}-\u{1F3FF}]|[\u{E0020}-\u{E007F}]|\uFE0F|\u20E3)*|[\u{1F1E6}-\u{1F1FF}]{2}|[#*0-9]\uFE0F?\u20E3/du, // eslint-disable-next-line max-len, no-misleading-character-class EMOJI_SKIN_TONES: /[\u{1f3fb}-\u{1f3ff}]/gu, + PRIVATE_USER_AREA: /[\uE000-\uF8FF\u{F0000}-\u{FFFFD}\u{100000}-\u{10FFFD}]/u, + + ONLY_PRIVATE_USER_AREA: /^[\uE000-\uF8FF\u{F0000}-\u{FFFFD}\u{100000}-\u{10FFFD}]+$/u, + TAX_ID: /^\d{9}$/, NON_NUMERIC: /\D/g, ANY_SPACE: /\s/g, diff --git a/src/components/EmojiWithTooltip/index.android.tsx b/src/components/EmojiWithTooltip/index.android.tsx index f6e9ee17fff8..e3926c3be8fd 100644 --- a/src/components/EmojiWithTooltip/index.android.tsx +++ b/src/components/EmojiWithTooltip/index.android.tsx @@ -1,8 +1,13 @@ +import {useMemo} from 'react'; import Text from '@components/Text'; +import useThemeStyles from '@hooks/useThemeStyles'; +import {containsCustomEmoji} from '@libs/EmojiUtils'; import type EmojiWithTooltipProps from './types'; function EmojiWithTooltip({emojiCode, style = {}}: EmojiWithTooltipProps) { - return {emojiCode}; + const isCustomEmoji = useMemo(() => containsCustomEmoji(emojiCode), [emojiCode]); + const styles = useThemeStyles(); + return {emojiCode}; } EmojiWithTooltip.displayName = 'EmojiWithTooltip'; diff --git a/src/components/LHNOptionsList/OptionRowLHN.tsx b/src/components/LHNOptionsList/OptionRowLHN.tsx index b5a010b82eb3..802a884a9d45 100644 --- a/src/components/LHNOptionsList/OptionRowLHN.tsx +++ b/src/components/LHNOptionsList/OptionRowLHN.tsx @@ -22,6 +22,7 @@ import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import DateUtils from '@libs/DateUtils'; import DomUtils from '@libs/DomUtils'; +import {containsCustomEmoji as containsCustomEmojiUtils, containsOnlyCustomEmoji} from '@libs/EmojiUtils'; import {shouldOptionShowTooltip, shouldUseBoldText} from '@libs/OptionsListUtils'; import Parser from '@libs/Parser'; import Performance from '@libs/Performance'; @@ -36,6 +37,7 @@ import { isSystemChat, isThread, } from '@libs/ReportUtils'; +import TextWithEmojiFragment from '@pages/home/report/comment/TextWithEmojiFragment'; import {showContextMenu} from '@pages/home/report/ContextMenu/ReportActionContextMenu'; import FreeTrial from '@pages/settings/Subscription/FreeTrial'; import variables from '@styles/variables'; @@ -106,6 +108,11 @@ function OptionRowLHN({ : [styles.chatLinkRowPressable, styles.flexGrow1, styles.optionItemAvatarNameWrapper, styles.optionRow, styles.justifyContentCenter], ); + const alternateTextContainsCustomEmojiWithText = useMemo( + () => containsCustomEmojiUtils(optionItem?.alternateText) && !containsOnlyCustomEmoji(optionItem?.alternateText), + [optionItem?.alternateText], + ); + if (!optionItem && !isOptionFocused) { // rendering null as a render item causes the FlashList to render all // its children and consume significant memory on the first render. We can avoid this by @@ -187,7 +194,6 @@ function OptionRowLHN({ hideProductTrainingTooltip(); onSelectRow(optionItem, popoverAnchor); }; - return ( )} - {optionItem.alternateText ? ( + {!!optionItem.alternateText && ( - {Parser.htmlToText(optionItem.alternateText)} + {alternateTextContainsCustomEmojiWithText ? ( + + ) : ( + Parser.htmlToText(optionItem.alternateText) + )} - ) : null} + )} {optionItem?.descriptiveText ? ( diff --git a/src/components/Text.tsx b/src/components/Text.tsx index 763f9ee3fb22..daac84142a53 100644 --- a/src/components/Text.tsx +++ b/src/components/Text.tsx @@ -1,9 +1,10 @@ import type {ForwardedRef} from 'react'; -import React, {useContext} from 'react'; +import React, {useContext, useMemo} from 'react'; // eslint-disable-next-line no-restricted-imports import {Text as RNText, StyleSheet} from 'react-native'; import type {TextProps as RNTextProps, TextStyle} from 'react-native'; import useTheme from '@hooks/useTheme'; +import {containsOnlyCustomEmoji} from '@libs/EmojiUtils'; import type {FontUtilsType} from '@styles/utils/FontUtils'; import FontUtils from '@styles/utils/FontUtils'; import variables from '@styles/variables'; @@ -51,6 +52,14 @@ function Text( componentStyle.lineHeight = variables.fontSizeNormalHeight; } + const isOnlyCustomEmoji = useMemo(() => { + return typeof children === 'string' ? containsOnlyCustomEmoji(children) : false; + }, [children]); + + if (isOnlyCustomEmoji) { + componentStyle.fontFamily = FontUtils.fontFamily.single.CUSTOM_EMOJI_FONT?.fontFamily; + } + return ( tag const containsOnlyEmojis = containsOnlyEmojisUtil(text ?? ''); + const containsOnlyCustomEmoji = useMemo(() => containsOnlyCustomEmojiUtil(text), [text]); const containsEmojis = CONST.REGEX.ALL_EMOJIS.test(text ?? ''); if (!shouldRenderAsText(html, text ?? '') && !(containsOnlyEmojis && styleAsDeleted)) { const editedTag = fragment?.isEdited ? `` : ''; @@ -129,6 +130,7 @@ function TextCommentFragment({fragment, styleAsDeleted, reportActionID, styleAsM styleAsDeleted ? styles.offlineFeedback.deleted : undefined, styleAsMuted ? styles.colorMuted : undefined, !canUseTouchScreen() || !shouldUseNarrowLayout ? styles.userSelectText : styles.userSelectNone, + containsOnlyCustomEmoji && styles.customEmojiFont, ]} > {convertToLTR(message ?? '')} diff --git a/src/pages/home/report/comment/TextWithEmojiFragment/index.ios.tsx b/src/pages/home/report/comment/TextWithEmojiFragment/index.ios.tsx index 538ca4e9deb6..b4942ab2274b 100644 --- a/src/pages/home/report/comment/TextWithEmojiFragment/index.ios.tsx +++ b/src/pages/home/report/comment/TextWithEmojiFragment/index.ios.tsx @@ -3,12 +3,12 @@ import {View} from 'react-native'; import Text from '@components/Text'; import useThemeStyles from '@hooks/useThemeStyles'; import convertToLTR from '@libs/convertToLTR'; -import * as EmojiUtils from '@libs/EmojiUtils'; +import {containsCustomEmoji, splitTextWithEmojis} from '@libs/EmojiUtils'; import type TextWithEmojiFragmentProps from './types'; function TextWithEmojiFragment({message = '', style}: TextWithEmojiFragmentProps) { const styles = useThemeStyles(); - const processedTextArray = useMemo(() => EmojiUtils.splitTextWithEmojis(message), [message]); + const processedTextArray = useMemo(() => splitTextWithEmojis(message), [message]); return ( @@ -18,7 +18,7 @@ function TextWithEmojiFragment({message = '', style}: TextWithEmojiFragmentProps // eslint-disable-next-line react/no-array-index-key key={index} > - {text} + {text} ) : ( convertToLTR(text) diff --git a/src/pages/home/report/comment/TextWithEmojiFragment/index.tsx b/src/pages/home/report/comment/TextWithEmojiFragment/index.tsx index d19725da766d..286e74ea99bb 100644 --- a/src/pages/home/report/comment/TextWithEmojiFragment/index.tsx +++ b/src/pages/home/report/comment/TextWithEmojiFragment/index.tsx @@ -2,13 +2,12 @@ import React, {useMemo} from 'react'; import Text from '@components/Text'; import useThemeStyles from '@hooks/useThemeStyles'; import convertToLTR from '@libs/convertToLTR'; -import * as EmojiUtils from '@libs/EmojiUtils'; +import {splitTextWithEmojis} from '@libs/EmojiUtils'; import type TextWithEmojiFragmentProps from './types'; -function TextWithEmojiFragment({message = '', style}: TextWithEmojiFragmentProps) { +function TextWithEmojiFragment({message = '', style, isAlternateText = false}: TextWithEmojiFragmentProps) { const styles = useThemeStyles(); - const processedTextArray = useMemo(() => EmojiUtils.splitTextWithEmojis(message), [message]); - + const processedTextArray = useMemo(() => splitTextWithEmojis(message), [message]); return ( {processedTextArray.map(({text, isEmoji}, index) => @@ -16,7 +15,7 @@ function TextWithEmojiFragment({message = '', style}: TextWithEmojiFragmentProps {text} diff --git a/src/pages/home/report/comment/TextWithEmojiFragment/types.ts b/src/pages/home/report/comment/TextWithEmojiFragment/types.ts index 243b02f1fd76..fc740096adaf 100644 --- a/src/pages/home/report/comment/TextWithEmojiFragment/types.ts +++ b/src/pages/home/report/comment/TextWithEmojiFragment/types.ts @@ -6,6 +6,9 @@ type TextWithEmojiFragmentProps = { /** Any additional styles to apply */ style: StyleProp; + + /** Whether the text is alternate text */ + isAlternateText?: boolean; }; export default TextWithEmojiFragmentProps; diff --git a/src/pages/home/report/comment/shouldRenderAsText/index.native.ts b/src/pages/home/report/comment/shouldRenderAsText/index.native.ts index ac68a9e660cf..4f772fce2740 100644 --- a/src/pages/home/report/comment/shouldRenderAsText/index.native.ts +++ b/src/pages/home/report/comment/shouldRenderAsText/index.native.ts @@ -1,4 +1,5 @@ import {Str} from 'expensify-common'; +import {containsCustomEmoji} from '@libs/EmojiUtils'; /** * Whether to render the report action as text @@ -8,5 +9,5 @@ export default function shouldRenderAsText(html: string, text: string): boolean // More info: https://github.com/Expensify/App/pull/35838#issuecomment-1964839350 const htmlWithoutLineBreak = Str.replaceAll(html, '
', '\n'); const htmlWithoutEmojiOpenTag = Str.replaceAll(htmlWithoutLineBreak, '', ''); - return Str.replaceAll(htmlWithoutEmojiOpenTag, '', '') === text; + return Str.replaceAll(htmlWithoutEmojiOpenTag, '', '') === text && !containsCustomEmoji(text); } diff --git a/src/styles/index.ts b/src/styles/index.ts index 37bdc57a6e1b..2cbbd2de03ca 100644 --- a/src/styles/index.ts +++ b/src/styles/index.ts @@ -315,6 +315,7 @@ const styles = (theme: ThemeColors) => ...spacing.p2, borderRadius: 8, }, + customEmojiFont: FontUtils.fontFamily.single.CUSTOM_EMOJI_FONT, mentionSuggestionsAvatarContainer: { width: 24, @@ -1903,6 +1904,10 @@ const styles = (theme: ThemeColors) => marginVertical: -7, }, + customEmojiFontAlignment: { + marginTop: -variables.fontSizeNormal, + }, + emojisFontFamily: { fontFamily: FontUtils.fontFamily.platform.SYSTEM.fontFamily, }, diff --git a/src/styles/utils/FontUtils/fontFamily/multiFontFamily/index.ts b/src/styles/utils/FontUtils/fontFamily/multiFontFamily/index.ts index 38a22e39b9df..c13db75f77db 100644 --- a/src/styles/utils/FontUtils/fontFamily/multiFontFamily/index.ts +++ b/src/styles/utils/FontUtils/fontFamily/multiFontFamily/index.ts @@ -36,7 +36,7 @@ const fontFamily: FontFamilyStyles = { }, EXP_NEUE: { - fontFamily: 'Expensify Neue, Segoe UI Emoji, Noto Color Emoji', + fontFamily: 'Expensify Neue, Segoe UI Emoji, Noto Color Emoji, Custom Emoji Font', fontStyle: 'normal', fontWeight: fontWeight.normal, }, @@ -66,6 +66,9 @@ const fontFamily: FontFamilyStyles = { fontStyle: 'italic', fontWeight: fontWeight.medium, }, + CUSTOM_EMOJI_FONT: { + fontFamily: 'Custom Emoji Font', + }, }; if (getOperatingSystem() === CONST.OS.WINDOWS) { diff --git a/src/styles/utils/FontUtils/fontFamily/singleFontFamily/index.ts b/src/styles/utils/FontUtils/fontFamily/singleFontFamily/index.ts index 496d1a32648f..701ce1be94ab 100644 --- a/src/styles/utils/FontUtils/fontFamily/singleFontFamily/index.ts +++ b/src/styles/utils/FontUtils/fontFamily/singleFontFamily/index.ts @@ -62,6 +62,11 @@ const fontFamily: FontFamilyStyles = { fontStyle: 'italic', fontWeight: fontWeight.medium, }, + CUSTOM_EMOJI_FONT: { + fontFamily: 'Custom Emoji Font', + fontStyle: 'normal', + fontWeight: fontWeight.normal, + }, }; export default fontFamily; diff --git a/src/styles/utils/FontUtils/fontFamily/types.ts b/src/styles/utils/FontUtils/fontFamily/types.ts index b3fcf2964804..5a6e16832e1b 100644 --- a/src/styles/utils/FontUtils/fontFamily/types.ts +++ b/src/styles/utils/FontUtils/fontFamily/types.ts @@ -11,12 +11,13 @@ type FontFamilyKey = | 'EXP_NEUE_ITALIC' | 'EXP_NEUE_BOLD_ITALIC' | 'EXP_NEW_KANSAS_MEDIUM' - | 'EXP_NEW_KANSAS_MEDIUM_ITALIC'; + | 'EXP_NEW_KANSAS_MEDIUM_ITALIC' + | 'CUSTOM_EMOJI_FONT'; type FontFamily = { fontFamily: string; - fontStyle: TextStyle['fontStyle']; - fontWeight: TextStyle['fontWeight']; + fontStyle?: TextStyle['fontStyle']; + fontWeight?: TextStyle['fontWeight']; }; type FontFamilyStyles = Record;