From 8d93e580e3629f763c2236d4f32ec06bf0142636 Mon Sep 17 00:00:00 2001 From: VickyStash Date: Mon, 5 Aug 2024 13:04:15 +0200 Subject: [PATCH 01/33] WIP on emojis enlarge --- src/CONST.ts | 8 ++- .../HTMLRenderers/EmojiRenderer.tsx | 14 +++- .../InlineCodeBlock/WrappedText.tsx | 2 +- src/libs/EmojiUtils.ts | 64 +++++++++++++++++- src/libs/ValidationUtils.ts | 4 +- .../home/report/ReportActionItemFragment.tsx | 17 ++--- .../index.native.tsx | 67 +++++++++++++++++++ .../index.tsx | 47 +++++++++++++ .../report/comment/TextCommentFragment.tsx | 48 +++++++++---- .../TextWithEmojiFragment/index.native.tsx | 59 ++++++++++++++++ .../comment/TextWithEmojiFragment/index.tsx | 51 ++++++++++++++ src/styles/index.ts | 7 ++ src/styles/variables.ts | 11 +-- 13 files changed, 360 insertions(+), 39 deletions(-) create mode 100644 src/pages/home/report/ReportActionItemMessageHeaderSender/index.native.tsx create mode 100644 src/pages/home/report/ReportActionItemMessageHeaderSender/index.tsx create mode 100644 src/pages/home/report/comment/TextWithEmojiFragment/index.native.tsx create mode 100644 src/pages/home/report/comment/TextWithEmojiFragment/index.tsx diff --git a/src/CONST.ts b/src/CONST.ts index ed4de999c78c..c59a67a02b41 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -2306,8 +2306,8 @@ 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 - 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/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, // eslint-disable-next-line max-len, no-misleading-character-class EMOJI_SKIN_TONES: /[\u{1f3fb}-\u{1f3ff}]/gu, @@ -2345,6 +2345,10 @@ const CONST = { return new RegExp(`[\\n\\s]|${this.SPECIAL_CHAR.source}|${this.EMOJI.source}`, 'gu'); }, + get ALL_EMOJIS() { + return new RegExp(CONST.REGEX.EMOJIS, CONST.REGEX.EMOJIS.flags.concat('g')); + }, + MERGED_ACCOUNT_PREFIX: /^(MERGED_\d+@)/, ROUTES: { diff --git a/src/components/HTMLEngineProvider/HTMLRenderers/EmojiRenderer.tsx b/src/components/HTMLEngineProvider/HTMLRenderers/EmojiRenderer.tsx index 9ad138444b9c..2764f4edbe7e 100644 --- a/src/components/HTMLEngineProvider/HTMLRenderers/EmojiRenderer.tsx +++ b/src/components/HTMLEngineProvider/HTMLRenderers/EmojiRenderer.tsx @@ -1,11 +1,21 @@ -import React from 'react'; +import React, {useMemo} from 'react'; import type {CustomRendererProps, TPhrasing, TText} from 'react-native-render-html'; import EmojiWithTooltip from '@components/EmojiWithTooltip'; import useThemeStyles from '@hooks/useThemeStyles'; function EmojiRenderer({tnode}: CustomRendererProps) { const styles = useThemeStyles(); - const style = 'islarge' in tnode.attributes ? styles.onlyEmojisText : {}; + const style = useMemo(() => { + if ('islarge' in tnode.attributes) { + return styles.onlyEmojisText; + } + + if ('ismedium' in tnode.attributes) { + return [styles.emojisWithTextFontSize, styles.verticalAlignMiddle]; + } + + return null; + }, [tnode.attributes, styles]); return ( Emojis.emojiNameTable[name]; @@ -148,7 +152,7 @@ function trimEmojiUnicode(emojiCode: string): string { */ function isFirstLetterEmoji(message: string): boolean { const trimmedMessage = Str.replaceAll(message.replace(/ /g, ''), '\n', ''); - const match = trimmedMessage.match(CONST.REGEX.EMOJIS); + const match = trimmedMessage.match(CONST.REGEX.ALL_EMOJIS); if (!match) { return false; @@ -162,7 +166,7 @@ function isFirstLetterEmoji(message: string): boolean { */ function containsOnlyEmojis(message: string): boolean { const trimmedMessage = Str.replaceAll(message.replace(/ /g, ''), '\n', ''); - const match = trimmedMessage.match(CONST.REGEX.EMOJIS); + const match = trimmedMessage.match(CONST.REGEX.ALL_EMOJIS); if (!match) { return false; @@ -285,7 +289,7 @@ function extractEmojis(text: string): Emoji[] { } // Parse Emojis including skin tones - Eg: ['👩🏻', '👩🏻', '👩🏼', '👩🏻', '👩🏼', '👩'] - const parsedEmojis = text.match(CONST.REGEX.EMOJIS); + const parsedEmojis = text.match(CONST.REGEX.ALL_EMOJIS); if (!parsedEmojis) { return []; @@ -586,6 +590,59 @@ function getSpacersIndexes(allEmojis: EmojiPickerList): number[] { return spacersIndexes; } +/** Splits the text with emojis into array if emojis exist in the text */ +function splitTextWithEmojis(text = ''): TextWithEmoji[] { + if (!text) { + return []; + } + + const doesTextContainEmojis = CONST.REGEX.ALL_EMOJIS.test(text); + + if (!doesTextContainEmojis) { + return []; + } + + // The regex needs to be cloned because `exec()` is a stateful operation and maintains the state inside + // the regex variable itself, so we must have an independent instance for each function's call. + const emojisRegex = CONST.REGEX.ALL_EMOJIS; + + const splitText: TextWithEmoji[] = []; + let regexResult: RegExpExecArray | null; + let lastMatchIndexEnd = 0; + + do { + regexResult = emojisRegex.exec(text); + + if (regexResult?.indices) { + const matchIndexStart = regexResult.indices[0][0]; + const matchIndexEnd = regexResult.indices[0][1]; + + if (matchIndexStart > lastMatchIndexEnd) { + splitText.push({ + text: text.slice(lastMatchIndexEnd, matchIndexStart), + isEmoji: false, + }); + } + + splitText.push({ + text: text.slice(matchIndexStart, matchIndexEnd), + isEmoji: true, + }); + + lastMatchIndexEnd = matchIndexEnd; + } + } while (regexResult !== null); + + if (lastMatchIndexEnd < text.length) { + splitText.push({ + text: text.slice(lastMatchIndexEnd, text.length), + isEmoji: false, + }); + } + + return splitText; +} + export type {HeaderIndice, EmojiPickerList, EmojiSpacer, EmojiPickerListItem}; export { @@ -611,4 +668,5 @@ export { hasAccountIDEmojiReacted, getRemovedSkinToneEmoji, getSpacersIndexes, + splitTextWithEmojis, }; diff --git a/src/libs/ValidationUtils.ts b/src/libs/ValidationUtils.ts index b0c99f4a6026..7e2b62fa8281 100644 --- a/src/libs/ValidationUtils.ts +++ b/src/libs/ValidationUtils.ts @@ -41,7 +41,7 @@ function isValidAddress(value: FormValue): boolean { return false; } - if (!CONST.REGEX.ANY_VALUE.test(value) || value.match(CONST.REGEX.EMOJIS)) { + if (!CONST.REGEX.ANY_VALUE.test(value) || value.match(CONST.REGEX.ALL_EMOJIS)) { return false; } @@ -331,7 +331,7 @@ function isValidRoutingNumber(routingNumber: string): boolean { * Checks that the provided name doesn't contain any emojis */ function isValidCompanyName(name: string) { - return !name.match(CONST.REGEX.EMOJIS); + return !name.match(CONST.REGEX.ALL_EMOJIS); } function isValidReportName(name: string) { diff --git a/src/pages/home/report/ReportActionItemFragment.tsx b/src/pages/home/report/ReportActionItemFragment.tsx index 787904d72b81..64b88045e385 100644 --- a/src/pages/home/report/ReportActionItemFragment.tsx +++ b/src/pages/home/report/ReportActionItemFragment.tsx @@ -2,12 +2,12 @@ import React, {memo} from 'react'; import type {StyleProp, TextStyle} from 'react-native'; import RenderHTML from '@components/RenderHTML'; import Text from '@components/Text'; -import UserDetailsTooltip from '@components/UserDetailsTooltip'; import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; import useThemeStyles from '@hooks/useThemeStyles'; import convertToLTR from '@libs/convertToLTR'; import * as ReportUtils from '@libs/ReportUtils'; +import ReportActionItemMessageHeaderSender from '@pages/home/report/ReportActionItemMessageHeaderSender'; import CONST from '@src/CONST'; import type * as OnyxCommon from '@src/types/onyx/OnyxCommon'; import type {DecisionName, OriginalMessageSource} from '@src/types/onyx/OriginalMessage'; @@ -160,18 +160,13 @@ function ReportActionItemFragment({ } return ( - - - {fragment?.text} - - + fragmentText={fragment.text} + actorIcon={actorIcon} + isSingleLine={isSingleLine} + /> ); } case 'LINK': diff --git a/src/pages/home/report/ReportActionItemMessageHeaderSender/index.native.tsx b/src/pages/home/report/ReportActionItemMessageHeaderSender/index.native.tsx new file mode 100644 index 000000000000..94da845f4030 --- /dev/null +++ b/src/pages/home/report/ReportActionItemMessageHeaderSender/index.native.tsx @@ -0,0 +1,67 @@ +import React, {useMemo} from 'react'; +import {View} from 'react-native'; +import Text from '@components/Text'; +import UserDetailsTooltip from '@components/UserDetailsTooltip'; +import useThemeStyles from '@hooks/useThemeStyles'; +import * as EmojiUtils from '@libs/EmojiUtils'; +import type * as OnyxCommon from '@src/types/onyx/OnyxCommon'; + +type ReportActionItemMessageHeaderSenderProps = { + /** Text to display */ + fragmentText: string; + + /** Users accountID */ + accountID: number; + + /** Should this fragment be contained in a single line? */ + isSingleLine?: boolean; + + /** The accountID of the copilot who took this action on behalf of the user */ + delegateAccountID?: number; + + /** Actor icon */ + actorIcon?: OnyxCommon.Icon; +}; + +function ReportActionItemMessageHeaderSender({fragmentText, accountID, delegateAccountID, actorIcon, isSingleLine}: ReportActionItemMessageHeaderSenderProps) { + const styles = useThemeStyles(); + const processedTextArray = useMemo(() => EmojiUtils.splitTextWithEmojis(fragmentText), [fragmentText]); + + return ( + + {processedTextArray.length !== 0 ? ( + + {processedTextArray.map(({text, isEmoji}) => + isEmoji ? ( + + 😁 + + ) : ( + + {text} + + ), + )} + + ) : ( + + {fragmentText} + + )} + + ); +} + +ReportActionItemMessageHeaderSender.displayName = 'ReportActionItemMessageHeaderSender'; + +export default ReportActionItemMessageHeaderSender; diff --git a/src/pages/home/report/ReportActionItemMessageHeaderSender/index.tsx b/src/pages/home/report/ReportActionItemMessageHeaderSender/index.tsx new file mode 100644 index 000000000000..7e4e21296db3 --- /dev/null +++ b/src/pages/home/report/ReportActionItemMessageHeaderSender/index.tsx @@ -0,0 +1,47 @@ +import React, {useMemo} from 'react'; +import Text from '@components/Text'; +import UserDetailsTooltip from '@components/UserDetailsTooltip'; +import useThemeStyles from '@hooks/useThemeStyles'; +import * as EmojiUtils from '@libs/EmojiUtils'; +import type * as OnyxCommon from '@src/types/onyx/OnyxCommon'; + +type ReportActionItemMessageHeaderSenderProps = { + /** Text to display */ + fragmentText: string; + + /** Users accountID */ + accountID: number; + + /** Should this fragment be contained in a single line? */ + isSingleLine?: boolean; + + /** The accountID of the copilot who took this action on behalf of the user */ + delegateAccountID?: number; + + /** Actor icon */ + actorIcon?: OnyxCommon.Icon; +}; + +function ReportActionItemMessageHeaderSender({fragmentText, accountID, delegateAccountID, actorIcon, isSingleLine}: ReportActionItemMessageHeaderSenderProps) { + const styles = useThemeStyles(); + const processedTextArray = useMemo(() => EmojiUtils.splitTextWithEmojis(fragmentText), [fragmentText]); + + return ( + + + {processedTextArray.length !== 0 ? processedTextArray.map(({text, isEmoji}) => (isEmoji ? {text} : text)) : fragmentText} + + + ); +} + +ReportActionItemMessageHeaderSender.displayName = 'ReportActionItemMessageHeaderSender'; + +export default ReportActionItemMessageHeaderSender; diff --git a/src/pages/home/report/comment/TextCommentFragment.tsx b/src/pages/home/report/comment/TextCommentFragment.tsx index 68827de96172..4722271492e7 100644 --- a/src/pages/home/report/comment/TextCommentFragment.tsx +++ b/src/pages/home/report/comment/TextCommentFragment.tsx @@ -1,6 +1,6 @@ import {Str} from 'expensify-common'; import {isEmpty} from 'lodash'; -import React, {memo} from 'react'; +import React, {memo, useMemo} from 'react'; import type {StyleProp, TextStyle} from 'react-native'; import Text from '@components/Text'; import ZeroWidthView from '@components/ZeroWidthView'; @@ -17,6 +17,7 @@ import type {OriginalMessageSource} from '@src/types/onyx/OriginalMessage'; import type {Message} from '@src/types/onyx/ReportAction'; import RenderCommentHTML from './RenderCommentHTML'; import shouldRenderAsText from './shouldRenderAsText'; +import TextWithEmojiFragment from './TextWithEmojiFragment'; type TextCommentFragmentProps = { /** The reportAction's source */ @@ -56,7 +57,14 @@ function TextCommentFragment({fragment, styleAsDeleted, styleAsMuted = false, so const editedTag = fragment?.isEdited ? `` : ''; const htmlWithDeletedTag = styleAsDeleted ? `${html}` : html; - const htmlContent = containsOnlyEmojis ? Str.replaceAll(htmlWithDeletedTag, '', '') : htmlWithDeletedTag; + let htmlContent = htmlWithDeletedTag; + + if (containsOnlyEmojis) { + htmlContent = Str.replaceAll(htmlWithDeletedTag, '', ''); + } else if (CONST.REGEX.ALL_EMOJIS.test(text ?? '')) { + htmlContent = Str.replaceAll(htmlWithDeletedTag, '', ''); + } + let htmlWithTag = editedTag ? `${htmlContent}${editedTag}` : htmlContent; if (styleAsMuted) { @@ -73,24 +81,36 @@ function TextCommentFragment({fragment, styleAsDeleted, styleAsMuted = false, so const message = isEmpty(iouMessage) ? text : iouMessage; + const processedTextArray = useMemo(() => EmojiUtils.splitTextWithEmojis(message), [message]); + return ( - - {convertToLTR(message ?? '')} - + {processedTextArray.length !== 0 ? ( + + ) : ( + + {convertToLTR(message ?? '')} + + )} {fragment?.isEdited && ( <> ; + + /** Should this message fragment be styled as deleted? */ + styleAsDeleted?: boolean; + + /** Should this message fragment be styled as muted? */ + styleAsMuted?: boolean; + + /** Does message contain only emojis? */ + hasEmojisOnly?: boolean; +}; + +function TextWithEmojiFragment({message, passedStyles, styleAsDeleted, styleAsMuted, hasEmojisOnly}: TextWithEmojiFragmentProps) { + const styles = useThemeStyles(); + const {shouldUseNarrowLayout} = useResponsiveLayout(); + + const processedTextArray = useMemo(() => EmojiUtils.splitTextWithEmojis(message), [message]); + + return ( + + {processedTextArray.map(({text: textik, isEmoji}) => + isEmoji ? ( + + {textik} + + ) : ( + convertToLTR(textik ?? '') + ), + )} + + ); +} + +TextWithEmojiFragment.displayName = 'TextWithEmojiFragment'; + +export default TextWithEmojiFragment; diff --git a/src/pages/home/report/comment/TextWithEmojiFragment/index.tsx b/src/pages/home/report/comment/TextWithEmojiFragment/index.tsx new file mode 100644 index 000000000000..bff42cd15b24 --- /dev/null +++ b/src/pages/home/report/comment/TextWithEmojiFragment/index.tsx @@ -0,0 +1,51 @@ +import React, {useMemo} from 'react'; +import type {StyleProp, TextStyle} from 'react-native'; +import Text from '@components/Text'; +import useResponsiveLayout from '@hooks/useResponsiveLayout'; +import useThemeStyles from '@hooks/useThemeStyles'; +import convertToLTR from '@libs/convertToLTR'; +import * as DeviceCapabilities from '@libs/DeviceCapabilities'; +import * as EmojiUtils from '@libs/EmojiUtils'; + +type TextWithEmojiFragmentProps = { + /** The message to be displayed */ + message: string; + + /** Additional styles to add after local styles. */ + passedStyles?: StyleProp; + + /** Should this message fragment be styled as deleted? */ + styleAsDeleted?: boolean; + + /** Should this message fragment be styled as muted? */ + styleAsMuted?: boolean; + + /** Does message contain only emojis? */ + hasEmojisOnly?: boolean; +}; + +function TextWithEmojiFragment({message, passedStyles, styleAsDeleted, styleAsMuted, hasEmojisOnly}: TextWithEmojiFragmentProps) { + const styles = useThemeStyles(); + const {shouldUseNarrowLayout} = useResponsiveLayout(); + + const processedTextArray = useMemo(() => EmojiUtils.splitTextWithEmojis(message), [message]); + + return ( + + {processedTextArray.map(({text: textik, isEmoji}) => (isEmoji ? {textik} : convertToLTR(textik ?? '')))} + + ); +} + +TextWithEmojiFragment.displayName = 'TextWithEmojiFragment'; + +export default TextWithEmojiFragment; diff --git a/src/styles/index.ts b/src/styles/index.ts index b3cb5b624bac..d6e52eca8348 100644 --- a/src/styles/index.ts +++ b/src/styles/index.ts @@ -362,6 +362,9 @@ const styles = (theme: ThemeColors) => textAlign: 'left', }, + verticalAlignMiddle: { + verticalAlign: 'middle', + }, verticalAlignTop: { verticalAlign: 'top', }, @@ -1710,6 +1713,10 @@ const styles = (theme: ThemeColors) => lineHeight: variables.fontSizeOnlyEmojisHeight, }, + emojisWithTextFontSize: { + fontSize: variables.fontSizeEmojisWithinText, + }, + createMenuPositionSidebar: (windowHeight: number) => ({ horizontal: 18, diff --git a/src/styles/variables.ts b/src/styles/variables.ts index e0720ad1d836..624134afa179 100644 --- a/src/styles/variables.ts +++ b/src/styles/variables.ts @@ -48,8 +48,6 @@ export default { defaultAvatarPreviewSize: 360, fabBottom: 25, breadcrumbsFontSize: getValueUsingPixelRatio(19, 32), - fontSizeOnlyEmojis: 30, - fontSizeOnlyEmojisHeight: 35, fontSizeSmall: getValueUsingPixelRatio(11, 17), fontSizeExtraSmall: 9, fontSizeLabel: getValueUsingPixelRatio(13, 19), @@ -87,8 +85,6 @@ export default { sidebarAvatarSize: 28, iconHeader: 48, iconSection: 68, - emojiSize: 20, - emojiLineHeight: 28, iouAmountTextSize: 40, extraSmallMobileResponsiveWidthBreakpoint: 320, extraSmallMobileResponsiveHeightBreakpoint: 667, @@ -213,6 +209,13 @@ export default { welcomeVideoDelay: 1000, explanationModalDelay: 2000, + // Emoji related variables + fontSizeOnlyEmojis: 30, + fontSizeOnlyEmojisHeight: 35, + emojiSize: 20, + emojiLineHeight: 28, + fontSizeEmojisWithinText: 19, + // The height of the empty list is 14px (2px for borders and 12px for vertical padding) // This is calculated based on the values specified in the 'getGoogleListViewStyle' function of the 'StyleUtils' utility googleEmptyListViewHeight: 14, From 8fdd879c32d4d2a493d6ea72951d645e1805fa27 Mon Sep 17 00:00:00 2001 From: VickyStash Date: Thu, 8 Aug 2024 11:56:33 +0200 Subject: [PATCH 02/33] Add more options for testing --- .../TextWithEmojiFragment/index.native.tsx | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/pages/home/report/comment/TextWithEmojiFragment/index.native.tsx b/src/pages/home/report/comment/TextWithEmojiFragment/index.native.tsx index 365308ea9e7b..67a8055659c6 100644 --- a/src/pages/home/report/comment/TextWithEmojiFragment/index.native.tsx +++ b/src/pages/home/report/comment/TextWithEmojiFragment/index.native.tsx @@ -1,5 +1,6 @@ import React, {useMemo} from 'react'; -import {StyleProp, TextStyle, View} from 'react-native'; +import {View} from 'react-native'; +import type {StyleProp, TextStyle} from 'react-native'; import Text from '@components/Text'; import useResponsiveLayout from '@hooks/useResponsiveLayout'; import useThemeStyles from '@hooks/useThemeStyles'; @@ -41,15 +42,21 @@ function TextWithEmojiFragment({message, passedStyles, styleAsDeleted, styleAsMu !DeviceCapabilities.canUseTouchScreen() || !shouldUseNarrowLayout ? styles.userSelectText : styles.userSelectNone, ]} > - {processedTextArray.map(({text: textik, isEmoji}) => + {processedTextArray.map(({text: textItem, isEmoji}) => isEmoji ? ( - {textik} + {textItem} ) : ( - convertToLTR(textik ?? '') + convertToLTR(textItem ?? '') ), )} + + {/* Option 2 */} + {/* {processedTextArray.map(({text: textItem, isEmoji}) => (isEmoji ? {textItem} : convertToLTR(textItem ?? '')))} */} + + {/* Option 3 - with 15 font size */} + {/* {processedTextArray.map(({text: textItem, isEmoji}) => (isEmoji ? {textItem} : convertToLTR(textItem ?? '')))} */} ); } From 1a776abfac0b86940e50956d271802cb610a65fc Mon Sep 17 00:00:00 2001 From: VickyStash Date: Mon, 12 Aug 2024 11:31:24 +0200 Subject: [PATCH 03/33] Improve messages with enlarged emojis display --- .../HTMLRenderers/EmojiRenderer.tsx | 2 +- src/hooks/useMarkdownStyle.ts | 2 +- .../index.native.tsx | 2 +- .../index.tsx | 4 +- .../report/comment/TextCommentFragment.tsx | 22 +++++---- .../TextWithEmojiFragment/index.native.tsx | 48 +++---------------- .../comment/TextWithEmojiFragment/index.tsx | 40 ++-------------- .../comment/TextWithEmojiFragment/types.ts | 11 +++++ src/styles/index.ts | 9 +++- src/styles/variables.ts | 3 +- 10 files changed, 48 insertions(+), 95 deletions(-) create mode 100644 src/pages/home/report/comment/TextWithEmojiFragment/types.ts diff --git a/src/components/HTMLEngineProvider/HTMLRenderers/EmojiRenderer.tsx b/src/components/HTMLEngineProvider/HTMLRenderers/EmojiRenderer.tsx index 2764f4edbe7e..023ca07beb63 100644 --- a/src/components/HTMLEngineProvider/HTMLRenderers/EmojiRenderer.tsx +++ b/src/components/HTMLEngineProvider/HTMLRenderers/EmojiRenderer.tsx @@ -11,7 +11,7 @@ function EmojiRenderer({tnode}: CustomRendererProps) { } if ('ismedium' in tnode.attributes) { - return [styles.emojisWithTextFontSize, styles.verticalAlignMiddle]; + return [styles.emojisWithTextFontSizeXLarge, styles.verticalAlignMiddle]; } return null; diff --git a/src/hooks/useMarkdownStyle.ts b/src/hooks/useMarkdownStyle.ts index c7e9bf2c0218..1a04bddd31a6 100644 --- a/src/hooks/useMarkdownStyle.ts +++ b/src/hooks/useMarkdownStyle.ts @@ -10,7 +10,7 @@ const defaultEmptyArray: Array = []; function useMarkdownStyle(message: string | null = null, excludeStyles: Array = defaultEmptyArray): MarkdownStyle { const theme = useTheme(); const hasMessageOnlyEmojis = message != null && message.length > 0 && containsOnlyEmojis(message); - const emojiFontSize = hasMessageOnlyEmojis ? variables.fontSizeOnlyEmojis : variables.fontSizeNormal; + const emojiFontSize = hasMessageOnlyEmojis ? variables.fontSizeOnlyEmojis : variables.fontSizeEmojisWithinTextLarge; // this map is used to reset the styles that are not needed - passing undefined value can break the native side const nonStylingDefaultValues: Record = useMemo( diff --git a/src/pages/home/report/ReportActionItemMessageHeaderSender/index.native.tsx b/src/pages/home/report/ReportActionItemMessageHeaderSender/index.native.tsx index 94da845f4030..bb00418772eb 100644 --- a/src/pages/home/report/ReportActionItemMessageHeaderSender/index.native.tsx +++ b/src/pages/home/report/ReportActionItemMessageHeaderSender/index.native.tsx @@ -38,7 +38,7 @@ function ReportActionItemMessageHeaderSender({fragmentText, accountID, delegateA {processedTextArray.map(({text, isEmoji}) => isEmoji ? ( - 😁 + 😁 ) : ( - {processedTextArray.length !== 0 ? processedTextArray.map(({text, isEmoji}) => (isEmoji ? {text} : text)) : fragmentText} + {processedTextArray.length !== 0 + ? processedTextArray.map(({text, isEmoji}) => (isEmoji ? {text} : text)) + : fragmentText} ); diff --git a/src/pages/home/report/comment/TextCommentFragment.tsx b/src/pages/home/report/comment/TextCommentFragment.tsx index 4722271492e7..32ffa4c64ed1 100644 --- a/src/pages/home/report/comment/TextCommentFragment.tsx +++ b/src/pages/home/report/comment/TextCommentFragment.tsx @@ -49,6 +49,10 @@ function TextCommentFragment({fragment, styleAsDeleted, styleAsMuted = false, so const {translate} = useLocalize(); const {shouldUseNarrowLayout} = useResponsiveLayout(); + const message = isEmpty(iouMessage) ? text : iouMessage; + + const processedTextArray = useMemo(() => EmojiUtils.splitTextWithEmojis(message), [message]); + // If the only difference between fragment.text and fragment.html is
tags and emoji tag // on native, we render it as text, not as html // on other device, only render it as text if the only difference is
tag @@ -79,23 +83,23 @@ function TextCommentFragment({fragment, styleAsDeleted, styleAsMuted = false, so ); } - const message = isEmpty(iouMessage) ? text : iouMessage; - - const processedTextArray = useMemo(() => EmojiUtils.splitTextWithEmojis(message), [message]); - return ( - {processedTextArray.length !== 0 ? ( + {processedTextArray.length !== 0 && !containsOnlyEmojis ? ( ) : ( ; - - /** Should this message fragment be styled as deleted? */ - styleAsDeleted?: boolean; - - /** Should this message fragment be styled as muted? */ - styleAsMuted?: boolean; - - /** Does message contain only emojis? */ - hasEmojisOnly?: boolean; -}; - -function TextWithEmojiFragment({message, passedStyles, styleAsDeleted, styleAsMuted, hasEmojisOnly}: TextWithEmojiFragmentProps) { +function TextWithEmojiFragment({message = '', style}: TextWithEmojiFragmentProps) { const styles = useThemeStyles(); - const {shouldUseNarrowLayout} = useResponsiveLayout(); - const processedTextArray = useMemo(() => EmojiUtils.splitTextWithEmojis(message), [message]); return ( - - {processedTextArray.map(({text: textItem, isEmoji}) => + + {processedTextArray.map(({text, isEmoji}) => isEmoji ? ( - {textItem} + {text} ) : ( - convertToLTR(textItem ?? '') + convertToLTR(text) ), )} - - {/* Option 2 */} - {/* {processedTextArray.map(({text: textItem, isEmoji}) => (isEmoji ? {textItem} : convertToLTR(textItem ?? '')))} */} - - {/* Option 3 - with 15 font size */} - {/* {processedTextArray.map(({text: textItem, isEmoji}) => (isEmoji ? {textItem} : convertToLTR(textItem ?? '')))} */} ); } diff --git a/src/pages/home/report/comment/TextWithEmojiFragment/index.tsx b/src/pages/home/report/comment/TextWithEmojiFragment/index.tsx index bff42cd15b24..4bbb16dafc48 100644 --- a/src/pages/home/report/comment/TextWithEmojiFragment/index.tsx +++ b/src/pages/home/report/comment/TextWithEmojiFragment/index.tsx @@ -1,49 +1,15 @@ import React, {useMemo} from 'react'; -import type {StyleProp, TextStyle} from 'react-native'; import Text from '@components/Text'; -import useResponsiveLayout from '@hooks/useResponsiveLayout'; import useThemeStyles from '@hooks/useThemeStyles'; import convertToLTR from '@libs/convertToLTR'; -import * as DeviceCapabilities from '@libs/DeviceCapabilities'; import * as EmojiUtils from '@libs/EmojiUtils'; +import type TextWithEmojiFragmentProps from './types'; -type TextWithEmojiFragmentProps = { - /** The message to be displayed */ - message: string; - - /** Additional styles to add after local styles. */ - passedStyles?: StyleProp; - - /** Should this message fragment be styled as deleted? */ - styleAsDeleted?: boolean; - - /** Should this message fragment be styled as muted? */ - styleAsMuted?: boolean; - - /** Does message contain only emojis? */ - hasEmojisOnly?: boolean; -}; - -function TextWithEmojiFragment({message, passedStyles, styleAsDeleted, styleAsMuted, hasEmojisOnly}: TextWithEmojiFragmentProps) { +function TextWithEmojiFragment({message = '', style}: TextWithEmojiFragmentProps) { const styles = useThemeStyles(); - const {shouldUseNarrowLayout} = useResponsiveLayout(); - const processedTextArray = useMemo(() => EmojiUtils.splitTextWithEmojis(message), [message]); - return ( - - {processedTextArray.map(({text: textik, isEmoji}) => (isEmoji ? {textik} : convertToLTR(textik ?? '')))} - - ); + return {processedTextArray.map(({text, isEmoji}) => (isEmoji ? {text} : convertToLTR(text)))}; } TextWithEmojiFragment.displayName = 'TextWithEmojiFragment'; diff --git a/src/pages/home/report/comment/TextWithEmojiFragment/types.ts b/src/pages/home/report/comment/TextWithEmojiFragment/types.ts new file mode 100644 index 000000000000..243b02f1fd76 --- /dev/null +++ b/src/pages/home/report/comment/TextWithEmojiFragment/types.ts @@ -0,0 +1,11 @@ +import type {StyleProp, TextStyle} from 'react-native'; + +type TextWithEmojiFragmentProps = { + /** The message to be displayed */ + message?: string; + + /** Any additional styles to apply */ + style: StyleProp; +}; + +export default TextWithEmojiFragmentProps; diff --git a/src/styles/index.ts b/src/styles/index.ts index d6e52eca8348..1592a66f5dbb 100644 --- a/src/styles/index.ts +++ b/src/styles/index.ts @@ -1713,8 +1713,13 @@ const styles = (theme: ThemeColors) => lineHeight: variables.fontSizeOnlyEmojisHeight, }, - emojisWithTextFontSize: { - fontSize: variables.fontSizeEmojisWithinText, + emojisWithTextFontSizeLarge: { + fontSize: variables.fontSizeEmojisWithinTextLarge, + marginVertical: -7, + }, + + emojisWithTextFontSizeXLarge: { + fontSize: variables.fontSizeEmojisWithinTextXLarge, }, createMenuPositionSidebar: (windowHeight: number) => diff --git a/src/styles/variables.ts b/src/styles/variables.ts index 624134afa179..dba6c7a0681b 100644 --- a/src/styles/variables.ts +++ b/src/styles/variables.ts @@ -214,7 +214,8 @@ export default { fontSizeOnlyEmojisHeight: 35, emojiSize: 20, emojiLineHeight: 28, - fontSizeEmojisWithinText: 19, + fontSizeEmojisWithinTextLarge: getValueUsingPixelRatio(17, 19), + fontSizeEmojisWithinTextXLarge: 19, // The height of the empty list is 14px (2px for borders and 12px for vertical padding) // This is calculated based on the values specified in the 'getGoogleListViewStyle' function of the 'StyleUtils' utility From 957737a9545ba51bb183f370249aa3a4ae68d650 Mon Sep 17 00:00:00 2001 From: VickyStash Date: Mon, 12 Aug 2024 14:09:50 +0200 Subject: [PATCH 04/33] Code clean up --- .../HTMLRenderers/EmojiRenderer.tsx | 3 +- src/hooks/useMarkdownStyle.ts | 3 +- .../index.native.tsx | 53 ++++--------------- .../index.tsx | 23 +------- .../types.ts | 20 +++++++ .../TextWithEmojiFragment/index.native.tsx | 2 +- .../comment/TextWithEmojiFragment/index.tsx | 2 +- src/styles/index.ts | 16 ++++-- src/styles/variables.ts | 3 +- 9 files changed, 50 insertions(+), 75 deletions(-) create mode 100644 src/pages/home/report/ReportActionItemMessageHeaderSender/types.ts diff --git a/src/components/HTMLEngineProvider/HTMLRenderers/EmojiRenderer.tsx b/src/components/HTMLEngineProvider/HTMLRenderers/EmojiRenderer.tsx index 023ca07beb63..7f087db98e14 100644 --- a/src/components/HTMLEngineProvider/HTMLRenderers/EmojiRenderer.tsx +++ b/src/components/HTMLEngineProvider/HTMLRenderers/EmojiRenderer.tsx @@ -11,7 +11,8 @@ function EmojiRenderer({tnode}: CustomRendererProps) { } if ('ismedium' in tnode.attributes) { - return [styles.emojisWithTextFontSizeXLarge, styles.verticalAlignMiddle]; + // TODO: Think about other approaches to align text selection {lineHeight: 22, marginTop: -2} + return [styles.emojisWithTextFontSize, styles.verticalAlignMiddle, {lineHeight: 22, marginTop: -2}]; } return null; diff --git a/src/hooks/useMarkdownStyle.ts b/src/hooks/useMarkdownStyle.ts index 1a04bddd31a6..8acc766a469c 100644 --- a/src/hooks/useMarkdownStyle.ts +++ b/src/hooks/useMarkdownStyle.ts @@ -10,7 +10,7 @@ const defaultEmptyArray: Array = []; function useMarkdownStyle(message: string | null = null, excludeStyles: Array = defaultEmptyArray): MarkdownStyle { const theme = useTheme(); const hasMessageOnlyEmojis = message != null && message.length > 0 && containsOnlyEmojis(message); - const emojiFontSize = hasMessageOnlyEmojis ? variables.fontSizeOnlyEmojis : variables.fontSizeEmojisWithinTextLarge; + const emojiFontSize = hasMessageOnlyEmojis ? variables.fontSizeOnlyEmojis : variables.fontSizeEmojisWithinText; // this map is used to reset the styles that are not needed - passing undefined value can break the native side const nonStylingDefaultValues: Record = useMemo( @@ -38,6 +38,7 @@ function useMarkdownStyle(message: string | null = null, excludeStyles: Array - {processedTextArray.length !== 0 ? ( - - {processedTextArray.map(({text, isEmoji}) => - isEmoji ? ( - - 😁 - - ) : ( - - {text} - - ), - )} - - ) : ( - - {fragmentText} - - )} + + {processedTextArray.length !== 0 + ? processedTextArray.map(({text, isEmoji}) => (isEmoji ? {text} : text)) + : fragmentText} + ); } diff --git a/src/pages/home/report/ReportActionItemMessageHeaderSender/index.tsx b/src/pages/home/report/ReportActionItemMessageHeaderSender/index.tsx index 8b0b31f445c4..e86087ee58c3 100644 --- a/src/pages/home/report/ReportActionItemMessageHeaderSender/index.tsx +++ b/src/pages/home/report/ReportActionItemMessageHeaderSender/index.tsx @@ -3,24 +3,7 @@ import Text from '@components/Text'; import UserDetailsTooltip from '@components/UserDetailsTooltip'; import useThemeStyles from '@hooks/useThemeStyles'; import * as EmojiUtils from '@libs/EmojiUtils'; -import type * as OnyxCommon from '@src/types/onyx/OnyxCommon'; - -type ReportActionItemMessageHeaderSenderProps = { - /** Text to display */ - fragmentText: string; - - /** Users accountID */ - accountID: number; - - /** Should this fragment be contained in a single line? */ - isSingleLine?: boolean; - - /** The accountID of the copilot who took this action on behalf of the user */ - delegateAccountID?: number; - - /** Actor icon */ - actorIcon?: OnyxCommon.Icon; -}; +import type ReportActionItemMessageHeaderSenderProps from './types'; function ReportActionItemMessageHeaderSender({fragmentText, accountID, delegateAccountID, actorIcon, isSingleLine}: ReportActionItemMessageHeaderSenderProps) { const styles = useThemeStyles(); @@ -36,9 +19,7 @@ function ReportActionItemMessageHeaderSender({fragmentText, accountID, delegateA numberOfLines={isSingleLine ? 1 : undefined} style={[styles.chatItemMessageHeaderSender, isSingleLine ? styles.pre : styles.preWrap, styles.dFlex]} > - {processedTextArray.length !== 0 - ? processedTextArray.map(({text, isEmoji}) => (isEmoji ? {text} : text)) - : fragmentText} + {processedTextArray.length !== 0 ? processedTextArray.map(({text, isEmoji}) => (isEmoji ? {text} : text)) : fragmentText} ); diff --git a/src/pages/home/report/ReportActionItemMessageHeaderSender/types.ts b/src/pages/home/report/ReportActionItemMessageHeaderSender/types.ts new file mode 100644 index 000000000000..44a27de119e6 --- /dev/null +++ b/src/pages/home/report/ReportActionItemMessageHeaderSender/types.ts @@ -0,0 +1,20 @@ +import type * as OnyxCommon from '@src/types/onyx/OnyxCommon'; + +type ReportActionItemMessageHeaderSenderProps = { + /** Text to display */ + fragmentText: string; + + /** Users accountID */ + accountID: number; + + /** Should this fragment be contained in a single line? */ + isSingleLine?: boolean; + + /** The accountID of the copilot who took this action on behalf of the user */ + delegateAccountID?: number; + + /** Actor icon */ + actorIcon?: OnyxCommon.Icon; +}; + +export default ReportActionItemMessageHeaderSenderProps; diff --git a/src/pages/home/report/comment/TextWithEmojiFragment/index.native.tsx b/src/pages/home/report/comment/TextWithEmojiFragment/index.native.tsx index 47133a1def0a..f4efeefc6623 100644 --- a/src/pages/home/report/comment/TextWithEmojiFragment/index.native.tsx +++ b/src/pages/home/report/comment/TextWithEmojiFragment/index.native.tsx @@ -15,7 +15,7 @@ function TextWithEmojiFragment({message = '', style}: TextWithEmojiFragmentProps {processedTextArray.map(({text, isEmoji}) => isEmoji ? ( - {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 4bbb16dafc48..e21a53451f2b 100644 --- a/src/pages/home/report/comment/TextWithEmojiFragment/index.tsx +++ b/src/pages/home/report/comment/TextWithEmojiFragment/index.tsx @@ -9,7 +9,7 @@ function TextWithEmojiFragment({message = '', style}: TextWithEmojiFragmentProps const styles = useThemeStyles(); const processedTextArray = useMemo(() => EmojiUtils.splitTextWithEmojis(message), [message]); - return {processedTextArray.map(({text, isEmoji}) => (isEmoji ? {text} : convertToLTR(text)))}; + return {processedTextArray.map(({text, isEmoji}) => (isEmoji ? {text} : convertToLTR(text)))}; } TextWithEmojiFragment.displayName = 'TextWithEmojiFragment'; diff --git a/src/styles/index.ts b/src/styles/index.ts index 1592a66f5dbb..480b4aaedf81 100644 --- a/src/styles/index.ts +++ b/src/styles/index.ts @@ -1713,13 +1713,21 @@ const styles = (theme: ThemeColors) => lineHeight: variables.fontSizeOnlyEmojisHeight, }, - emojisWithTextFontSizeLarge: { - fontSize: variables.fontSizeEmojisWithinTextLarge, + emojisWithTextFontSizeAligned: { + fontSize: variables.fontSizeEmojisWithinText, marginVertical: -7, }, - emojisWithTextFontSizeXLarge: { - fontSize: variables.fontSizeEmojisWithinTextXLarge, + emojisWithTextFontSize: { + fontSize: variables.fontSizeEmojisWithinText, + }, + + emojisWithTextFontFamily: { + fontFamily: FontUtils.fontFamily.platform.SYSTEM.fontFamily, + }, + + emojisWithTextLineHeight: { + lineHeight: variables.lineHeightXLarge, }, createMenuPositionSidebar: (windowHeight: number) => diff --git a/src/styles/variables.ts b/src/styles/variables.ts index dba6c7a0681b..39ff79f9c914 100644 --- a/src/styles/variables.ts +++ b/src/styles/variables.ts @@ -214,8 +214,7 @@ export default { fontSizeOnlyEmojisHeight: 35, emojiSize: 20, emojiLineHeight: 28, - fontSizeEmojisWithinTextLarge: getValueUsingPixelRatio(17, 19), - fontSizeEmojisWithinTextXLarge: 19, + fontSizeEmojisWithinText: getValueUsingPixelRatio(17, 19), // The height of the empty list is 14px (2px for borders and 12px for vertical padding) // This is calculated based on the values specified in the 'getGoogleListViewStyle' function of the 'StyleUtils' utility From 27fb058652f91c912e0b57279d8cc614a16c4532 Mon Sep 17 00:00:00 2001 From: VickyStash Date: Wed, 14 Aug 2024 16:32:51 +0200 Subject: [PATCH 05/33] Fix composer height when only emojis are entered --- src/components/Composer/index.native.tsx | 6 +++++- src/components/Composer/index.tsx | 3 ++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/components/Composer/index.native.tsx b/src/components/Composer/index.native.tsx index 68a8c56c4df9..e5d20ebfb294 100644 --- a/src/components/Composer/index.native.tsx +++ b/src/components/Composer/index.native.tsx @@ -24,6 +24,7 @@ function Composer( maxLines, isComposerFullSize = false, setIsFullComposerAvailable = () => {}, + isFullComposerAvailable = false, autoFocus = false, style, // On native layers we like to have the Text Input not focused so the @@ -71,7 +72,10 @@ function Composer( ); const maxHeightStyle = useMemo(() => StyleUtils.getComposerMaxHeightStyle(maxLines, isComposerFullSize), [StyleUtils, isComposerFullSize, maxLines]); - const composerStyle = useMemo(() => StyleSheet.flatten([style, textContainsOnlyEmojis ? styles.onlyEmojisTextLineHeight : {}]), [style, textContainsOnlyEmojis, styles]); + const composerStyle = useMemo( + () => StyleSheet.flatten([style, textContainsOnlyEmojis && isFullComposerAvailable ? styles.onlyEmojisTextLineHeight : {}]), + [style, textContainsOnlyEmojis, isFullComposerAvailable, styles], + ); return ( Date: Wed, 14 Aug 2024 17:23:31 +0200 Subject: [PATCH 06/33] Increase emojis in the display name --- src/pages/settings/InitialSettingsPage.tsx | 35 ++++++++++++------- .../settings/Profile/DisplayNamePage.tsx | 2 ++ src/styles/index.ts | 4 +++ src/styles/variables.ts | 1 + 4 files changed, 30 insertions(+), 12 deletions(-) diff --git a/src/pages/settings/InitialSettingsPage.tsx b/src/pages/settings/InitialSettingsPage.tsx index bc98a9432630..648690505dc0 100755 --- a/src/pages/settings/InitialSettingsPage.tsx +++ b/src/pages/settings/InitialSettingsPage.tsx @@ -29,6 +29,7 @@ import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import useWaitForNavigation from '@hooks/useWaitForNavigation'; import * as CurrencyUtils from '@libs/CurrencyUtils'; +import * as EmojiUtils from '@libs/EmojiUtils'; import Navigation from '@libs/Navigation/Navigation'; import * as SubscriptionUtils from '@libs/SubscriptionUtils'; import * as UserUtils from '@libs/UserUtils'; @@ -364,9 +365,10 @@ function InitialSettingsPage({session, userWallet, bankAccountList, fundList, wa const generalMenuItems = useMemo(() => getMenuItemsSection(generalMenuItemsData), [generalMenuItemsData, getMenuItemsSection]); const workspaceMenuItems = useMemo(() => getMenuItemsSection(workspaceMenuItemsData), [workspaceMenuItemsData, getMenuItemsSection]); - const currentUserDetails = currentUserPersonalDetails; - const avatarURL = currentUserDetails?.avatar ?? ''; - const accountID = currentUserDetails?.accountID ?? '-1'; + const avatarURL = currentUserPersonalDetails?.avatar ?? ''; + const accountID = currentUserPersonalDetails?.accountID ?? '-1'; + + const processedTextArray = useMemo(() => EmojiUtils.splitTextWithEmojis(currentUserPersonalDetails?.displayName), [currentUserPersonalDetails]); const headerContent = ( @@ -416,7 +418,7 @@ function InitialSettingsPage({session, userWallet, bankAccountList, fundList, wa Navigation.navigate(ROUTES.PROFILE_AVATAR.getRoute(String(accountID)))} previewSource={UserUtils.getFullSizeAvatar(avatarURL, accountID)} - originalFileName={currentUserDetails.originalFileName} + originalFileName={currentUserPersonalDetails?.originalFileName} headerTitle={translate('profilePage.profileAvatar')} - fallbackIcon={currentUserDetails?.fallbackIcon} + fallbackIcon={currentUserPersonalDetails?.fallbackIcon} editIconStyle={styles.smallEditIconAccount} /> - - {currentUserPersonalDetails.displayName ? currentUserPersonalDetails.displayName : formatPhoneNumber(session?.email ?? '')} - + {processedTextArray.length !== 0 ? ( + + {processedTextArray.map(({text, isEmoji}) => (isEmoji ? {text} : text))} + + ) : ( + + {currentUserPersonalDetails.displayName ? currentUserPersonalDetails.displayName : formatPhoneNumber(session?.email ?? '')} + + )} {!!currentUserPersonalDetails.displayName && ( @@ -114,6 +115,7 @@ function DisplayNamePage({isLoadingApp = true, currentUserPersonalDetails}: Disp role={CONST.ROLE.PRESENTATION} defaultValue={currentUserDetails.lastName ?? ''} spellCheck={false} + isMarkdownEnabled /> diff --git a/src/styles/index.ts b/src/styles/index.ts index 48aa36cfa1a8..8ac9be222799 100644 --- a/src/styles/index.ts +++ b/src/styles/index.ts @@ -1730,6 +1730,10 @@ const styles = (theme: ThemeColors) => lineHeight: variables.lineHeightXLarge, }, + initialSettingsUsernameEmoji: { + fontSize: variables.fontSizeUsernameEmoji, + }, + createMenuPositionSidebar: (windowHeight: number) => ({ horizontal: 18, diff --git a/src/styles/variables.ts b/src/styles/variables.ts index 87444ee23c58..ef8818cb939f 100644 --- a/src/styles/variables.ts +++ b/src/styles/variables.ts @@ -214,6 +214,7 @@ export default { fontSizeOnlyEmojisHeight: 35, emojiSize: 20, emojiLineHeight: 28, + fontSizeUsernameEmoji: 25, fontSizeEmojisWithinText: getValueUsingPixelRatio(17, 19), // The height of the empty list is 14px (2px for borders and 12px for vertical padding) From e75050100724094cbfb62589d69e6ce230556413 Mon Sep 17 00:00:00 2001 From: VickyStash Date: Fri, 16 Aug 2024 13:45:01 +0200 Subject: [PATCH 07/33] Fix emojis are cut off in some places on ios --- src/components/SelectionList/Search/UserInfoCell.tsx | 2 +- src/components/TextWithTooltip/index.native.tsx | 11 +++++++++-- src/styles/index.ts | 6 +++++- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/components/SelectionList/Search/UserInfoCell.tsx b/src/components/SelectionList/Search/UserInfoCell.tsx index 793c8c94c391..064033e6dcdc 100644 --- a/src/components/SelectionList/Search/UserInfoCell.tsx +++ b/src/components/SelectionList/Search/UserInfoCell.tsx @@ -30,7 +30,7 @@ function UserInfoCell({participant, displayName}: UserInfoCellProps) { /> {displayName} diff --git a/src/components/TextWithTooltip/index.native.tsx b/src/components/TextWithTooltip/index.native.tsx index b857ded2588b..bb3d9052b5b7 100644 --- a/src/components/TextWithTooltip/index.native.tsx +++ b/src/components/TextWithTooltip/index.native.tsx @@ -1,14 +1,21 @@ -import React from 'react'; +import React, {useMemo} from 'react'; import Text from '@components/Text'; +import useThemeStyles from '@hooks/useThemeStyles'; +import * as EmojiUtils from '@libs/EmojiUtils'; import type TextWithTooltipProps from './types'; function TextWithTooltip({text, style, numberOfLines = 1}: TextWithTooltipProps) { + const styles = useThemeStyles(); + const processedTextArray = useMemo(() => EmojiUtils.splitTextWithEmojis(text), [text]); + return ( - {text} + {processedTextArray.length !== 0 + ? processedTextArray.map(({text: textItem, isEmoji}) => (isEmoji ? {textItem} : textItem)) + : text} ); } diff --git a/src/styles/index.ts b/src/styles/index.ts index a73a3cf277f1..aefa1287a5eb 100644 --- a/src/styles/index.ts +++ b/src/styles/index.ts @@ -413,7 +413,7 @@ const styles = (theme: ThemeColors) => color: theme.text, ...FontUtils.fontFamily.platform.EXP_NEUE_BOLD, fontSize: variables.fontSizeSmall, - lineHeight: variables.lineHeightSmall, + lineHeight: variables.lineHeightNormal, }, textMicroSupporting: { @@ -1718,6 +1718,10 @@ const styles = (theme: ThemeColors) => marginVertical: -7, }, + emojisFontFamily: { + fontFamily: FontUtils.fontFamily.platform.SYSTEM.fontFamily, + }, + emojisWithTextFontSize: { fontSize: variables.fontSizeEmojisWithinText, }, From 3175d40c4b773f6abe5207eb526bc7d28f40d89f Mon Sep 17 00:00:00 2001 From: VickyStash Date: Fri, 16 Aug 2024 13:46:50 +0200 Subject: [PATCH 08/33] Lint fixes --- src/components/Composer/index.tsx | 2 +- src/pages/home/report/ReportActionItemFragment.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/Composer/index.tsx b/src/components/Composer/index.tsx index 15cfb3831348..b204513f5d93 100755 --- a/src/components/Composer/index.tsx +++ b/src/components/Composer/index.tsx @@ -383,7 +383,7 @@ function Composer( textContainsOnlyEmojis && isFullComposerAvailable ? styles.onlyEmojisTextLineHeight : {}, ], - [style, styles.rtlTextRenderForSafari, styles.onlyEmojisTextLineHeight, scrollStyleMemo, StyleUtils, maxLines, isComposerFullSize, textContainsOnlyEmojis], + [style, styles.rtlTextRenderForSafari, styles.onlyEmojisTextLineHeight, scrollStyleMemo, isFullComposerAvailable, StyleUtils, maxLines, isComposerFullSize, textContainsOnlyEmojis], ); return ( diff --git a/src/pages/home/report/ReportActionItemFragment.tsx b/src/pages/home/report/ReportActionItemFragment.tsx index 64b88045e385..05cb657b1e54 100644 --- a/src/pages/home/report/ReportActionItemFragment.tsx +++ b/src/pages/home/report/ReportActionItemFragment.tsx @@ -7,7 +7,6 @@ import useNetwork from '@hooks/useNetwork'; import useThemeStyles from '@hooks/useThemeStyles'; import convertToLTR from '@libs/convertToLTR'; import * as ReportUtils from '@libs/ReportUtils'; -import ReportActionItemMessageHeaderSender from '@pages/home/report/ReportActionItemMessageHeaderSender'; import CONST from '@src/CONST'; import type * as OnyxCommon from '@src/types/onyx/OnyxCommon'; import type {DecisionName, OriginalMessageSource} from '@src/types/onyx/OriginalMessage'; @@ -15,6 +14,7 @@ import type {Message} from '@src/types/onyx/ReportAction'; import type ReportActionName from '@src/types/onyx/ReportActionName'; import AttachmentCommentFragment from './comment/AttachmentCommentFragment'; import TextCommentFragment from './comment/TextCommentFragment'; +import ReportActionItemMessageHeaderSender from './ReportActionItemMessageHeaderSender'; type ReportActionItemFragmentProps = { /** Users accountID */ From 8b0828b0925e22dd0729010d88fe98e1915f2bd6 Mon Sep 17 00:00:00 2001 From: VickyStash Date: Fri, 16 Aug 2024 14:08:39 +0200 Subject: [PATCH 09/33] Try to fix react compiler error --- src/components/TextWithTooltip/index.native.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/TextWithTooltip/index.native.tsx b/src/components/TextWithTooltip/index.native.tsx index bb3d9052b5b7..892b34649d93 100644 --- a/src/components/TextWithTooltip/index.native.tsx +++ b/src/components/TextWithTooltip/index.native.tsx @@ -1,4 +1,4 @@ -import React, {useMemo} from 'react'; +import React from 'react'; import Text from '@components/Text'; import useThemeStyles from '@hooks/useThemeStyles'; import * as EmojiUtils from '@libs/EmojiUtils'; @@ -6,7 +6,7 @@ import type TextWithTooltipProps from './types'; function TextWithTooltip({text, style, numberOfLines = 1}: TextWithTooltipProps) { const styles = useThemeStyles(); - const processedTextArray = useMemo(() => EmojiUtils.splitTextWithEmojis(text), [text]); + const processedTextArray = EmojiUtils.splitTextWithEmojis(text); return ( Date: Mon, 19 Aug 2024 15:48:23 +0200 Subject: [PATCH 10/33] Resolve TODO related to the text selection --- .../HTMLEngineProvider/HTMLRenderers/EmojiRenderer.tsx | 3 +-- src/styles/index.ts | 3 +++ src/styles/utils/emojiDefaultStyles/index.ts | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/components/HTMLEngineProvider/HTMLRenderers/EmojiRenderer.tsx b/src/components/HTMLEngineProvider/HTMLRenderers/EmojiRenderer.tsx index 7f087db98e14..5d359b6f54a8 100644 --- a/src/components/HTMLEngineProvider/HTMLRenderers/EmojiRenderer.tsx +++ b/src/components/HTMLEngineProvider/HTMLRenderers/EmojiRenderer.tsx @@ -11,8 +11,7 @@ function EmojiRenderer({tnode}: CustomRendererProps) { } if ('ismedium' in tnode.attributes) { - // TODO: Think about other approaches to align text selection {lineHeight: 22, marginTop: -2} - return [styles.emojisWithTextFontSize, styles.verticalAlignMiddle, {lineHeight: 22, marginTop: -2}]; + return [styles.emojisWithTextFontSize, styles.verticalAlignTopText]; } return null; diff --git a/src/styles/index.ts b/src/styles/index.ts index aefa1287a5eb..a9351770890f 100644 --- a/src/styles/index.ts +++ b/src/styles/index.ts @@ -365,6 +365,9 @@ const styles = (theme: ThemeColors) => verticalAlignMiddle: { verticalAlign: 'middle', }, + verticalAlignTopText: { + verticalAlign: 'top-text', + }, verticalAlignTop: { verticalAlign: 'top', }, diff --git a/src/styles/utils/emojiDefaultStyles/index.ts b/src/styles/utils/emojiDefaultStyles/index.ts index 88c42e7e95d1..45880b46005d 100644 --- a/src/styles/utils/emojiDefaultStyles/index.ts +++ b/src/styles/utils/emojiDefaultStyles/index.ts @@ -6,7 +6,7 @@ import type EmojiDefaultStyles from './types'; const emojiDefaultStyles: EmojiDefaultStyles = { fontStyle: 'normal', fontWeight: FontUtils.fontWeight.normal, - ...display.dInlineFlex, + ...display.dInline, }; export default emojiDefaultStyles; From 41ffb05edbeb903abc763cc2f675a5f03965bea1 Mon Sep 17 00:00:00 2001 From: VickyStash Date: Tue, 20 Aug 2024 14:45:15 +0200 Subject: [PATCH 11/33] Fix cursor jumping on ios --- src/components/TextInput/BaseTextInput/index.native.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/TextInput/BaseTextInput/index.native.tsx b/src/components/TextInput/BaseTextInput/index.native.tsx index 59f205da023f..ffe30f4169f0 100644 --- a/src/components/TextInput/BaseTextInput/index.native.tsx +++ b/src/components/TextInput/BaseTextInput/index.native.tsx @@ -179,9 +179,10 @@ function BaseTextInput( } const layout = event.nativeEvent.layout; + const HEIGHT_TO_FIT_EMOJIS = 1; setWidth((prevWidth: number | null) => (autoGrowHeight ? layout.width : prevWidth)); - setHeight((prevHeight: number) => (!multiline ? layout.height : prevHeight)); + setHeight((prevHeight: number) => (!multiline ? layout.height + HEIGHT_TO_FIT_EMOJIS : prevHeight)); }, [autoGrowHeight, multiline], ); From 2007c58a43ff6f4b9f6fc000e6e40856346a83e4 Mon Sep 17 00:00:00 2001 From: VickyStash Date: Tue, 20 Aug 2024 15:15:10 +0200 Subject: [PATCH 12/33] Fix emojis are cut off in the workspace list on ios --- src/pages/workspace/WorkspacesListRow.tsx | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/pages/workspace/WorkspacesListRow.tsx b/src/pages/workspace/WorkspacesListRow.tsx index ac53252829fa..5e23e88cb167 100644 --- a/src/pages/workspace/WorkspacesListRow.tsx +++ b/src/pages/workspace/WorkspacesListRow.tsx @@ -16,6 +16,7 @@ import useLocalize from '@hooks/useLocalize'; import useResponsiveLayout from '@hooks/useResponsiveLayout'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; +import * as EmojiUtils from '@libs/EmojiUtils'; import * as PersonalDetailsUtils from '@libs/PersonalDetailsUtils'; import type {AvatarSource} from '@libs/UserUtils'; import type {AnchorPosition} from '@styles/index'; @@ -116,6 +117,8 @@ function WorkspacesListRow({ const {shouldUseNarrowLayout} = useResponsiveLayout(); const ownerDetails = ownerAccountID && PersonalDetailsUtils.getPersonalDetailsByIDs([ownerAccountID], currentUserPersonalDetails.accountID)[0]; + const ownerName = ownerDetails ? PersonalDetailsUtils.getDisplayNameOrDefault(ownerDetails) : ''; + const processedOwnerName = EmojiUtils.splitTextWithEmojis(ownerName); const userFriendlyWorkspaceType = useMemo(() => { switch (workspaceType) { @@ -221,7 +224,15 @@ function WorkspacesListRow({ numberOfLines={1} style={[styles.labelStrong, isDeleted ? styles.offlineFeedback.deleted : {}]} > - {PersonalDetailsUtils.getDisplayNameOrDefault(ownerDetails)} + {processedOwnerName.length !== 0 + ? processedOwnerName.map(({text, isEmoji}) => + isEmoji ? ( + {text} + ) : ( + text + ), + ) + : ownerName} Date: Tue, 20 Aug 2024 16:42:57 +0200 Subject: [PATCH 13/33] Fix composer height --- src/libs/ComposerUtils/updateIsFullComposerAvailable.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/ComposerUtils/updateIsFullComposerAvailable.ts b/src/libs/ComposerUtils/updateIsFullComposerAvailable.ts index c10635f1c491..eb83f5c06467 100644 --- a/src/libs/ComposerUtils/updateIsFullComposerAvailable.ts +++ b/src/libs/ComposerUtils/updateIsFullComposerAvailable.ts @@ -14,7 +14,7 @@ function updateIsFullComposerAvailable(props: ComposerProps, event: NativeSynthe return; } const totalHeight = inputHeight + paddingTopAndBottom; - const isFullComposerAvailable = totalHeight >= CONST.COMPOSER.FULL_COMPOSER_MIN_HEIGHT; + const isFullComposerAvailable = totalHeight > CONST.COMPOSER.FULL_COMPOSER_MIN_HEIGHT; if (isFullComposerAvailable !== props.isFullComposerAvailable) { props.setIsFullComposerAvailable?.(isFullComposerAvailable); } From 2dd77732a011d96c2db147ce11d5160b2365a701 Mon Sep 17 00:00:00 2001 From: VickyStash Date: Tue, 20 Aug 2024 17:29:55 +0200 Subject: [PATCH 14/33] Lint fix --- src/styles/index.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/styles/index.ts b/src/styles/index.ts index 609af3708ea2..1e157209a696 100644 --- a/src/styles/index.ts +++ b/src/styles/index.ts @@ -362,9 +362,6 @@ const styles = (theme: ThemeColors) => textAlign: 'left', }, - verticalAlignMiddle: { - verticalAlign: 'middle', - }, verticalAlignTopText: { verticalAlign: 'top-text', }, From cc8e8b173fff498db2845470432c9e0b23c730f5 Mon Sep 17 00:00:00 2001 From: VickyStash Date: Wed, 21 Aug 2024 10:59:50 +0200 Subject: [PATCH 15/33] Fix large emojis overlap --- src/components/Composer/index.native.tsx | 14 +++++++++----- src/components/Composer/index.tsx | 8 +++++--- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/components/Composer/index.native.tsx b/src/components/Composer/index.native.tsx index 2b6644cedceb..6f46699673e3 100644 --- a/src/components/Composer/index.native.tsx +++ b/src/components/Composer/index.native.tsx @@ -1,6 +1,6 @@ import type {MarkdownStyle} from '@expensify/react-native-live-markdown'; import type {ForwardedRef} from 'react'; -import React, {useCallback, useMemo, useRef} from 'react'; +import React, {useCallback, useMemo, useRef, useState} from 'react'; import type {NativeSyntheticEvent, TextInput, TextInputChangeEventData, TextInputPasteEventData} from 'react-native'; import {StyleSheet} from 'react-native'; import type {FileObject} from '@components/AttachmentModal'; @@ -13,6 +13,7 @@ import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import updateIsFullComposerAvailable from '@libs/ComposerUtils/updateIsFullComposerAvailable'; import * as EmojiUtils from '@libs/EmojiUtils'; +import variables from '@styles/variables'; import type {ComposerProps} from './types'; const excludeNoStyles: Array = []; @@ -26,7 +27,6 @@ function Composer( maxLines, isComposerFullSize = false, setIsFullComposerAvailable = () => {}, - isFullComposerAvailable = false, autoFocus = false, style, // On native layers we like to have the Text Input not focused so the @@ -40,6 +40,7 @@ function Composer( ref: ForwardedRef, ) { const textInput = useRef(null); + const [hasMultipleLines, setHasMultipleLines] = useState(false); const {isFocused, shouldResetFocusRef} = useResetComposerFocus(textInput); const textContainsOnlyEmojis = useMemo(() => EmojiUtils.containsOnlyEmojis(value ?? ''), [value]); const theme = useTheme(); @@ -89,8 +90,8 @@ function Composer( const maxHeightStyle = useMemo(() => StyleUtils.getComposerMaxHeightStyle(maxLines, isComposerFullSize), [StyleUtils, isComposerFullSize, maxLines]); const composerStyle = useMemo( - () => StyleSheet.flatten([style, textContainsOnlyEmojis && isFullComposerAvailable ? styles.onlyEmojisTextLineHeight : {}]), - [style, textContainsOnlyEmojis, isFullComposerAvailable, styles], + () => StyleSheet.flatten([style, textContainsOnlyEmojis && hasMultipleLines ? styles.onlyEmojisTextLineHeight : {}]), + [style, textContainsOnlyEmojis, hasMultipleLines, styles], ); return ( @@ -100,7 +101,10 @@ function Composer( placeholderTextColor={theme.placeholderText} ref={setTextInputRef} value={value} - onContentSizeChange={(e) => updateIsFullComposerAvailable({maxLines, isComposerFullSize, isDisabled, setIsFullComposerAvailable}, e, styles, true)} + onContentSizeChange={(e) => { + setHasMultipleLines(e.nativeEvent.contentSize.height > variables.componentSizeLarge); + updateIsFullComposerAvailable({maxLines, isComposerFullSize, isDisabled, setIsFullComposerAvailable}, e, styles, true); + }} rejectResponderTermination={false} smartInsertDelete={false} textAlignVertical="center" diff --git a/src/components/Composer/index.tsx b/src/components/Composer/index.tsx index e0a98ec80010..2847c6cc615b 100755 --- a/src/components/Composer/index.tsx +++ b/src/components/Composer/index.tsx @@ -21,6 +21,7 @@ import * as EmojiUtils from '@libs/EmojiUtils'; import * as FileUtils from '@libs/fileDownload/FileUtils'; import isEnterWhileComposition from '@libs/KeyboardShortcut/isEnterWhileComposition'; import ReportActionComposeFocusManager from '@libs/ReportActionComposeFocusManager'; +import variables from '@styles/variables'; import CONST from '@src/CONST'; import type {ComposerProps} from './types'; @@ -72,7 +73,6 @@ function Composer( end: 0, }, isReportActionCompose = false, - isFullComposerAvailable = false, isComposerFullSize = false, shouldContainScroll = true, isGroupPolicyReport = false, @@ -102,6 +102,7 @@ function Composer( const [caretContent, setCaretContent] = useState(''); const [valueBeforeCaret, setValueBeforeCaret] = useState(''); const [textInputWidth, setTextInputWidth] = useState(''); + const [hasMultipleLines, setHasMultipleLines] = useState(false); const [isRendered, setIsRendered] = useState(false); const isScrollBarVisible = useIsScrollBarVisible(textInput, value ?? ''); const [prevScroll, setPrevScroll] = useState(); @@ -380,10 +381,10 @@ function Composer( scrollStyleMemo, StyleUtils.getComposerMaxHeightStyle(maxLines, isComposerFullSize), isComposerFullSize ? {height: '100%', maxHeight: 'none'} : undefined, - textContainsOnlyEmojis && isFullComposerAvailable ? styles.onlyEmojisTextLineHeight : {}, + textContainsOnlyEmojis && hasMultipleLines ? styles.onlyEmojisTextLineHeight : {}, ], - [style, styles.rtlTextRenderForSafari, styles.onlyEmojisTextLineHeight, scrollStyleMemo, isFullComposerAvailable, StyleUtils, maxLines, isComposerFullSize, textContainsOnlyEmojis], + [style, styles.rtlTextRenderForSafari, styles.onlyEmojisTextLineHeight, scrollStyleMemo, hasMultipleLines, StyleUtils, maxLines, isComposerFullSize, textContainsOnlyEmojis], ); return ( @@ -403,6 +404,7 @@ function Composer( {...props} onSelectionChange={addCursorPositionToSelectionChange} onContentSizeChange={(e) => { + setHasMultipleLines(e.nativeEvent.contentSize.height > variables.componentSizeLarge); setTextInputWidth(`${e.nativeEvent.contentSize.width}px`); updateIsFullComposerAvailable({maxLines, isComposerFullSize, isDisabled, setIsFullComposerAvailable}, e, styles); }} From 435e777a3226436004143e0f6331741e2379aa7a Mon Sep 17 00:00:00 2001 From: VickyStash Date: Wed, 21 Aug 2024 11:40:26 +0200 Subject: [PATCH 16/33] Improve sender display --- .../home/report/ReportActionItemMessageHeaderSender/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/home/report/ReportActionItemMessageHeaderSender/index.tsx b/src/pages/home/report/ReportActionItemMessageHeaderSender/index.tsx index e86087ee58c3..d2bedbd3f18b 100644 --- a/src/pages/home/report/ReportActionItemMessageHeaderSender/index.tsx +++ b/src/pages/home/report/ReportActionItemMessageHeaderSender/index.tsx @@ -17,7 +17,7 @@ function ReportActionItemMessageHeaderSender({fragmentText, accountID, delegateA > {processedTextArray.length !== 0 ? processedTextArray.map(({text, isEmoji}) => (isEmoji ? {text} : text)) : fragmentText} From 6ef259587b965dbeffad504b177d8696d622c408 Mon Sep 17 00:00:00 2001 From: VickyStash Date: Fri, 23 Aug 2024 11:23:01 +0200 Subject: [PATCH 17/33] Lint fix --- src/pages/home/report/comment/TextCommentFragment.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/home/report/comment/TextCommentFragment.tsx b/src/pages/home/report/comment/TextCommentFragment.tsx index 93c884c3acf2..7c39ade32e40 100644 --- a/src/pages/home/report/comment/TextCommentFragment.tsx +++ b/src/pages/home/report/comment/TextCommentFragment.tsx @@ -1,6 +1,6 @@ import {Str} from 'expensify-common'; import {isEmpty} from 'lodash'; -import React, {memo, useMemo, useEffect} from 'react'; +import React, {memo, useEffect, useMemo} from 'react'; import type {StyleProp, TextStyle} from 'react-native'; import Text from '@components/Text'; import ZeroWidthView from '@components/ZeroWidthView'; From 7cf9b772607297081ba64fdb77a9a5a23c27e3b0 Mon Sep 17 00:00:00 2001 From: VickyStash Date: Mon, 26 Aug 2024 17:16:04 +0200 Subject: [PATCH 18/33] Fix emoji alignment --- src/styles/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/styles/index.ts b/src/styles/index.ts index ea9162322b2f..6176b7c1734b 100644 --- a/src/styles/index.ts +++ b/src/styles/index.ts @@ -363,7 +363,7 @@ const styles = (theme: ThemeColors) => }, verticalAlignTopText: { - verticalAlign: 'top-text', + verticalAlign: 'text-top', }, verticalAlignTop: { verticalAlign: 'top', From 272a32dae00750f45812d6a24ba630af99f0fc58 Mon Sep 17 00:00:00 2001 From: VickyStash Date: Thu, 29 Aug 2024 17:07:32 +0200 Subject: [PATCH 19/33] Update display name emoji size after merging main --- src/components/AccountSwitcher.tsx | 8 ++++++-- src/styles/variables.ts | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/components/AccountSwitcher.tsx b/src/components/AccountSwitcher.tsx index ba30ea0062b9..428ea27f0fe0 100644 --- a/src/components/AccountSwitcher.tsx +++ b/src/components/AccountSwitcher.tsx @@ -1,4 +1,4 @@ -import React, {useRef, useState} from 'react'; +import React, {useMemo, useRef, useState} from 'react'; import {View} from 'react-native'; import {useOnyx} from 'react-native-onyx'; import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; @@ -9,6 +9,7 @@ import useResponsiveLayout from '@hooks/useResponsiveLayout'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import {clearDelegatorErrors, connect, disconnect} from '@libs/actions/Delegate'; +import * as EmojiUtils from '@libs/EmojiUtils'; import * as PersonalDetailsUtils from '@libs/PersonalDetailsUtils'; import variables from '@styles/variables'; import * as Modal from '@userActions/Modal'; @@ -44,6 +45,7 @@ function AccountSwitcher() { const isActingAsDelegate = !!account?.delegatedAccess?.delegate ?? false; const canSwitchAccounts = canUseNewDotCopilot && (delegators.length > 0 || isActingAsDelegate); + const processedTextArray = useMemo(() => EmojiUtils.splitTextWithEmojis(currentUserPersonalDetails?.displayName), [currentUserPersonalDetails]); const createBaseMenuItem = (personalDetails: PersonalDetails | undefined, error?: TranslationPaths, additionalProps: MenuItemWithLink = {}): MenuItemWithLink => { return { @@ -143,7 +145,9 @@ function AccountSwitcher() { numberOfLines={1} style={[styles.textBold, styles.textLarge]} > - {currentUserPersonalDetails?.displayName} + {processedTextArray.length !== 0 + ? processedTextArray.map(({text, isEmoji}) => (isEmoji ? {text} : text)) + : currentUserPersonalDetails?.displayName} {canSwitchAccounts && ( diff --git a/src/styles/variables.ts b/src/styles/variables.ts index c1ae0646783f..91fd81e6ef44 100644 --- a/src/styles/variables.ts +++ b/src/styles/variables.ts @@ -217,7 +217,7 @@ export default { fontSizeOnlyEmojisHeight: 35, emojiSize: 20, emojiLineHeight: 28, - fontSizeUsernameEmoji: 25, + fontSizeUsernameEmoji: 19, fontSizeEmojisWithinText: getValueUsingPixelRatio(17, 19), // The height of the empty list is 14px (2px for borders and 12px for vertical padding) From 87e41e577c02ef18d65079f073fccd431465462b Mon Sep 17 00:00:00 2001 From: VickyStash Date: Thu, 29 Aug 2024 17:15:37 +0200 Subject: [PATCH 20/33] Compiler fix --- src/components/AccountSwitcher.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/AccountSwitcher.tsx b/src/components/AccountSwitcher.tsx index 428ea27f0fe0..faae7a481d66 100644 --- a/src/components/AccountSwitcher.tsx +++ b/src/components/AccountSwitcher.tsx @@ -1,4 +1,4 @@ -import React, {useMemo, useRef, useState} from 'react'; +import React, {useRef, useState} from 'react'; import {View} from 'react-native'; import {useOnyx} from 'react-native-onyx'; import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; @@ -45,7 +45,7 @@ function AccountSwitcher() { const isActingAsDelegate = !!account?.delegatedAccess?.delegate ?? false; const canSwitchAccounts = canUseNewDotCopilot && (delegators.length > 0 || isActingAsDelegate); - const processedTextArray = useMemo(() => EmojiUtils.splitTextWithEmojis(currentUserPersonalDetails?.displayName), [currentUserPersonalDetails]); + const processedTextArray = EmojiUtils.splitTextWithEmojis(currentUserPersonalDetails?.displayName); const createBaseMenuItem = (personalDetails: PersonalDetails | undefined, error?: TranslationPaths, additionalProps: MenuItemWithLink = {}): MenuItemWithLink => { return { From dda7fdf6745d212dad26b8676c456aa1efbd1381 Mon Sep 17 00:00:00 2001 From: VickyStash Date: Fri, 30 Aug 2024 11:22:38 +0200 Subject: [PATCH 21/33] Code improvement --- src/pages/home/report/comment/TextCommentFragment.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/pages/home/report/comment/TextCommentFragment.tsx b/src/pages/home/report/comment/TextCommentFragment.tsx index 7c39ade32e40..703baac97044 100644 --- a/src/pages/home/report/comment/TextCommentFragment.tsx +++ b/src/pages/home/report/comment/TextCommentFragment.tsx @@ -98,7 +98,6 @@ function TextCommentFragment({fragment, styleAsDeleted, styleAsMuted = false, so Date: Tue, 3 Sep 2024 17:27:00 +0200 Subject: [PATCH 22/33] Fix web emoji display --- .../index.native.tsx | 27 +++++++++++++++++++ .../WorkspacesListRowDisplayName/index.tsx | 21 +++++++++++++++ .../WorkspacesListRowDisplayName/types.tsx | 9 +++++++ src/pages/workspace/WorkspacesListRow.tsx | 22 ++++----------- 4 files changed, 62 insertions(+), 17 deletions(-) create mode 100644 src/components/WorkspacesListRowDisplayName/index.native.tsx create mode 100644 src/components/WorkspacesListRowDisplayName/index.tsx create mode 100644 src/components/WorkspacesListRowDisplayName/types.tsx diff --git a/src/components/WorkspacesListRowDisplayName/index.native.tsx b/src/components/WorkspacesListRowDisplayName/index.native.tsx new file mode 100644 index 000000000000..e9db04c18aae --- /dev/null +++ b/src/components/WorkspacesListRowDisplayName/index.native.tsx @@ -0,0 +1,27 @@ +import React from 'react'; +import Text from '@components/Text'; +import useThemeStyles from '@hooks/useThemeStyles'; +import * as EmojiUtils from '@libs/EmojiUtils'; +import type WorkspacesListRowDisplayNameProps from './types'; + +function WorkspacesListRowDisplayName({isDeleted, ownerName}: WorkspacesListRowDisplayNameProps) { + const styles = useThemeStyles(); + const processedOwnerName = EmojiUtils.splitTextWithEmojis(ownerName); + + return ( + + {processedOwnerName.length !== 0 + ? processedOwnerName.map(({text, isEmoji}) => + isEmoji ? {text} : text, + ) + : ownerName} + + ); +} + +WorkspacesListRowDisplayName.displayName = 'WorkspacesListRowDisplayName'; + +export default WorkspacesListRowDisplayName; diff --git a/src/components/WorkspacesListRowDisplayName/index.tsx b/src/components/WorkspacesListRowDisplayName/index.tsx new file mode 100644 index 000000000000..0d3acb736d2f --- /dev/null +++ b/src/components/WorkspacesListRowDisplayName/index.tsx @@ -0,0 +1,21 @@ +import React from 'react'; +import Text from '@components/Text'; +import useThemeStyles from '@hooks/useThemeStyles'; +import type WorkspacesListRowDisplayNameProps from './types'; + +function WorkspacesListRowDisplayName({isDeleted, ownerName}: WorkspacesListRowDisplayNameProps) { + const styles = useThemeStyles(); + + return ( + + {ownerName} + + ); +} + +WorkspacesListRowDisplayName.displayName = 'WorkspacesListRowDisplayName'; + +export default WorkspacesListRowDisplayName; diff --git a/src/components/WorkspacesListRowDisplayName/types.tsx b/src/components/WorkspacesListRowDisplayName/types.tsx new file mode 100644 index 000000000000..0744ebc18fc1 --- /dev/null +++ b/src/components/WorkspacesListRowDisplayName/types.tsx @@ -0,0 +1,9 @@ +type WorkspacesListRowDisplayNameProps = { + /** Should the deleted style be applied */ + isDeleted: boolean; + + /** Workspace owner name */ + ownerName: string; +}; + +export default WorkspacesListRowDisplayNameProps; diff --git a/src/pages/workspace/WorkspacesListRow.tsx b/src/pages/workspace/WorkspacesListRow.tsx index 5e23e88cb167..6b5d2230c039 100644 --- a/src/pages/workspace/WorkspacesListRow.tsx +++ b/src/pages/workspace/WorkspacesListRow.tsx @@ -12,11 +12,11 @@ import Text from '@components/Text'; import ThreeDotsMenu from '@components/ThreeDotsMenu'; import type {WithCurrentUserPersonalDetailsProps} from '@components/withCurrentUserPersonalDetails'; import withCurrentUserPersonalDetails from '@components/withCurrentUserPersonalDetails'; +import WorkspacesListRowDisplayName from '@components/WorkspacesListRowDisplayName'; import useLocalize from '@hooks/useLocalize'; import useResponsiveLayout from '@hooks/useResponsiveLayout'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; -import * as EmojiUtils from '@libs/EmojiUtils'; import * as PersonalDetailsUtils from '@libs/PersonalDetailsUtils'; import type {AvatarSource} from '@libs/UserUtils'; import type {AnchorPosition} from '@styles/index'; @@ -117,8 +117,6 @@ function WorkspacesListRow({ const {shouldUseNarrowLayout} = useResponsiveLayout(); const ownerDetails = ownerAccountID && PersonalDetailsUtils.getPersonalDetailsByIDs([ownerAccountID], currentUserPersonalDetails.accountID)[0]; - const ownerName = ownerDetails ? PersonalDetailsUtils.getDisplayNameOrDefault(ownerDetails) : ''; - const processedOwnerName = EmojiUtils.splitTextWithEmojis(ownerName); const userFriendlyWorkspaceType = useMemo(() => { switch (workspaceType) { @@ -220,20 +218,10 @@ function WorkspacesListRow({ containerStyles={styles.workspaceOwnerAvatarWrapper} /> - - {processedOwnerName.length !== 0 - ? processedOwnerName.map(({text, isEmoji}) => - isEmoji ? ( - {text} - ) : ( - text - ), - ) - : ownerName} - + Date: Wed, 11 Sep 2024 13:14:54 +0200 Subject: [PATCH 23/33] Add missed import --- src/components/AccountSwitcher.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/AccountSwitcher.tsx b/src/components/AccountSwitcher.tsx index 2d69463f7845..b6f89e097560 100644 --- a/src/components/AccountSwitcher.tsx +++ b/src/components/AccountSwitcher.tsx @@ -10,6 +10,7 @@ import useResponsiveLayout from '@hooks/useResponsiveLayout'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import {clearDelegatorErrors, connect, disconnect} from '@libs/actions/Delegate'; +import * as EmojiUtils from '@libs/EmojiUtils'; import * as ErrorUtils from '@libs/ErrorUtils'; import * as PersonalDetailsUtils from '@libs/PersonalDetailsUtils'; import variables from '@styles/variables'; From 528c08f5b91da0d4b91cb770820b929b904cab8f Mon Sep 17 00:00:00 2001 From: VickyStash Date: Thu, 12 Sep 2024 10:04:27 +0200 Subject: [PATCH 24/33] Fix regex usage --- src/CONST.ts | 2 +- src/libs/EmojiUtils.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/CONST.ts b/src/CONST.ts index 96374cb2dd1a..173f7d876b98 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -2551,7 +2551,7 @@ const CONST = { }, get ALL_EMOJIS() { - return new RegExp(CONST.REGEX.EMOJIS, CONST.REGEX.EMOJIS.flags.concat('g')); + return new RegExp(this.EMOJIS, this.EMOJIS.flags.concat('g')); }, MERGED_ACCOUNT_PREFIX: /^(MERGED_\d+@)/, diff --git a/src/libs/EmojiUtils.ts b/src/libs/EmojiUtils.ts index 5ff3ff40e4c1..09c4fd0d0a60 100644 --- a/src/libs/EmojiUtils.ts +++ b/src/libs/EmojiUtils.ts @@ -604,7 +604,7 @@ function splitTextWithEmojis(text = ''): TextWithEmoji[] { // The regex needs to be cloned because `exec()` is a stateful operation and maintains the state inside // the regex variable itself, so we must have an independent instance for each function's call. - const emojisRegex = CONST.REGEX.ALL_EMOJIS; + const emojisRegex = new RegExp(CONST.REGEX.EMOJIS, CONST.REGEX.EMOJIS.flags.concat('g')); const splitText: TextWithEmoji[] = []; let regexResult: RegExpExecArray | null; From eb3a9585a09de11ae11af2569cdf693487bc64db Mon Sep 17 00:00:00 2001 From: VickyStash Date: Thu, 12 Sep 2024 11:09:54 +0200 Subject: [PATCH 25/33] Fix only emojis cropping in the composer on ios --- src/components/Composer/index.native.tsx | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/src/components/Composer/index.native.tsx b/src/components/Composer/index.native.tsx index a95881031683..9b886aa49c1d 100644 --- a/src/components/Composer/index.native.tsx +++ b/src/components/Composer/index.native.tsx @@ -1,7 +1,7 @@ import type {MarkdownStyle} from '@expensify/react-native-live-markdown'; import mimeDb from 'mime-db'; import type {ForwardedRef} from 'react'; -import React, {useCallback, useEffect, useMemo, useRef, useState} from 'react'; +import React, {useCallback, useEffect, useMemo, useRef} from 'react'; import type {NativeSyntheticEvent, TextInput, TextInputChangeEventData, TextInputPasteEventData} from 'react-native'; import {StyleSheet} from 'react-native'; import type {FileObject} from '@components/AttachmentModal'; @@ -16,7 +16,6 @@ import useThemeStyles from '@hooks/useThemeStyles'; import updateIsFullComposerAvailable from '@libs/ComposerUtils/updateIsFullComposerAvailable'; import * as EmojiUtils from '@libs/EmojiUtils'; import * as FileUtils from '@libs/fileDownload/FileUtils'; -import variables from '@styles/variables'; import type {ComposerProps} from './types'; const excludeNoStyles: Array = []; @@ -43,7 +42,6 @@ function Composer( ref: ForwardedRef, ) { const textInput = useRef(null); - const [hasMultipleLines, setHasMultipleLines] = useState(false); const {isFocused, shouldResetFocusRef} = useResetComposerFocus(textInput); const textContainsOnlyEmojis = useMemo(() => EmojiUtils.containsOnlyEmojis(value ?? ''), [value]); const theme = useTheme(); @@ -109,10 +107,7 @@ function Composer( ); const maxHeightStyle = useMemo(() => StyleUtils.getComposerMaxHeightStyle(maxLines, isComposerFullSize), [StyleUtils, isComposerFullSize, maxLines]); - const composerStyle = useMemo( - () => StyleSheet.flatten([style, textContainsOnlyEmojis && hasMultipleLines ? styles.onlyEmojisTextLineHeight : {}]), - [style, textContainsOnlyEmojis, hasMultipleLines, styles], - ); + const composerStyle = useMemo(() => StyleSheet.flatten([style, textContainsOnlyEmojis ? styles.onlyEmojisTextLineHeight : {}]), [style, textContainsOnlyEmojis, styles]); return ( { - setHasMultipleLines(e.nativeEvent.contentSize.height > variables.componentSizeLarge); - updateIsFullComposerAvailable({maxLines, isComposerFullSize, isDisabled, setIsFullComposerAvailable}, e, styles, true); - }} + onContentSizeChange={(e) => updateIsFullComposerAvailable({maxLines, isComposerFullSize, isDisabled, setIsFullComposerAvailable}, e, styles, true)} rejectResponderTermination={false} smartInsertDelete={false} textAlignVertical="center" From 4713c7e94cc49bdcd53963252b6b1e27d03109bd Mon Sep 17 00:00:00 2001 From: VickyStash Date: Mon, 23 Sep 2024 10:53:49 +0200 Subject: [PATCH 26/33] Fix lint check errors --- src/libs/ValidationUtils.ts | 2 +- .../settings/Profile/DisplayNamePage.tsx | 20 +++++-------------- 2 files changed, 6 insertions(+), 16 deletions(-) diff --git a/src/libs/ValidationUtils.ts b/src/libs/ValidationUtils.ts index 10c74865bb51..a1c1b44ccaf7 100644 --- a/src/libs/ValidationUtils.ts +++ b/src/libs/ValidationUtils.ts @@ -21,7 +21,7 @@ import StringUtils from './StringUtils'; function validateCardNumber(value: string): boolean { let sum = 0; for (let i = 0; i < value.length; i++) { - let intVal = parseInt(value.substr(i, 1), 10); + let intVal = parseInt(value.charAt(i), 10); if (i % 2 === 0) { intVal *= 2; if (intVal > 9) { diff --git a/src/pages/settings/Profile/DisplayNamePage.tsx b/src/pages/settings/Profile/DisplayNamePage.tsx index 35f5d77cb124..4c6211bc3e37 100644 --- a/src/pages/settings/Profile/DisplayNamePage.tsx +++ b/src/pages/settings/Profile/DisplayNamePage.tsx @@ -1,7 +1,6 @@ import React from 'react'; import {View} from 'react-native'; -import type {OnyxEntry} from 'react-native-onyx'; -import {withOnyx} from 'react-native-onyx'; +import {useOnyx} from 'react-native-onyx'; import FormProvider from '@components/Form/FormProvider'; import InputWrapper from '@components/Form/InputWrapper'; import type {FormInputErrors, FormOnyxValues} from '@components/Form/types'; @@ -22,11 +21,7 @@ import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import INPUT_IDS from '@src/types/form/DisplayNameForm'; -type DisplayNamePageOnyxProps = { - isLoadingApp: OnyxEntry; -}; - -type DisplayNamePageProps = DisplayNamePageOnyxProps & WithCurrentUserPersonalDetailsProps; +type DisplayNamePageProps = WithCurrentUserPersonalDetailsProps; /** * Submit form to update user's first and last name (and display name) @@ -36,9 +31,10 @@ const updateDisplayName = (values: FormOnyxValues({ - isLoadingApp: { - key: ONYXKEYS.IS_LOADING_APP, - }, - })(DisplayNamePage), -); +export default withCurrentUserPersonalDetails(DisplayNamePage); From 70190a45ee96f2f9fa75c74e492a3ec1d84d7512 Mon Sep 17 00:00:00 2001 From: VickyStash Date: Tue, 1 Oct 2024 10:45:48 +0200 Subject: [PATCH 27/33] Minor fix --- src/libs/EmojiUtils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/EmojiUtils.ts b/src/libs/EmojiUtils.ts index 09c4fd0d0a60..9b1f1806e94f 100644 --- a/src/libs/EmojiUtils.ts +++ b/src/libs/EmojiUtils.ts @@ -596,7 +596,7 @@ function splitTextWithEmojis(text = ''): TextWithEmoji[] { return []; } - const doesTextContainEmojis = CONST.REGEX.ALL_EMOJIS.test(text); + const doesTextContainEmojis = new RegExp(CONST.REGEX.EMOJIS, CONST.REGEX.EMOJIS.flags.concat('g')).test(text); if (!doesTextContainEmojis) { return []; From bce816dc449b2c94aa14bc96514998c38fdbb29c Mon Sep 17 00:00:00 2001 From: VickyStash Date: Fri, 4 Oct 2024 09:31:15 +0200 Subject: [PATCH 28/33] TS fix --- .../HTMLEngineProvider/HTMLRenderers/EmojiRenderer.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/components/HTMLEngineProvider/HTMLRenderers/EmojiRenderer.tsx b/src/components/HTMLEngineProvider/HTMLRenderers/EmojiRenderer.tsx index fd9152092c05..879684210825 100644 --- a/src/components/HTMLEngineProvider/HTMLRenderers/EmojiRenderer.tsx +++ b/src/components/HTMLEngineProvider/HTMLRenderers/EmojiRenderer.tsx @@ -1,4 +1,5 @@ import React, {useMemo} from 'react'; +import type {TextStyle} from 'react-native'; import type {CustomRendererProps, TPhrasing, TText} from 'react-native-render-html'; import EmojiWithTooltip from '@components/EmojiWithTooltip'; import useThemeStyles from '@hooks/useThemeStyles'; @@ -7,15 +8,15 @@ function EmojiRenderer({tnode, style: styleProp}: CustomRendererProps { if ('islarge' in tnode.attributes) { - return [styleProp, styles.onlyEmojisText]; + return [styleProp as TextStyle, styles.onlyEmojisText]; } if ('ismedium' in tnode.attributes) { - return [styleProp, styles.emojisWithTextFontSize, styles.verticalAlignTopText]; + return [styleProp as TextStyle, styles.emojisWithTextFontSize, styles.verticalAlignTopText]; } return null; - }, [tnode.attributes, styles]); + }, [tnode.attributes, styles, styleProp]); return ( Date: Fri, 4 Oct 2024 09:40:52 +0200 Subject: [PATCH 29/33] Update react-native-live-markdown version --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index cf9978bae510..87e6d11c5829 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "license": "MIT", "dependencies": { "@dotlottie/react-player": "^1.6.3", - "@expensify/react-native-live-markdown": "0.1.143", + "@expensify/react-native-live-markdown": "0.1.163", "@expo/metro-runtime": "~3.2.3", "@firebase/app": "^0.10.10", "@firebase/performance": "^0.6.8", @@ -3634,9 +3634,9 @@ } }, "node_modules/@expensify/react-native-live-markdown": { - "version": "0.1.143", - "resolved": "https://registry.npmjs.org/@expensify/react-native-live-markdown/-/react-native-live-markdown-0.1.143.tgz", - "integrity": "sha512-hZXYjKyTl/b2p7Ig9qhoB7cfVtTTcoE2cWvea8NJT3f5ZYckdyHDAgHI4pg0S0N68jP205Sk5pzqlltZUpZk5w==", + "version": "0.1.163", + "resolved": "https://registry.npmjs.org/@expensify/react-native-live-markdown/-/react-native-live-markdown-0.1.163.tgz", + "integrity": "sha512-kIVWxKPHbXrLJ28TmI4sOndFjo8LktoytSiea4tS/GhVQXkbzZdtyTzNVfrQPSsJq+ITUbg701aC5XNqDhIAnQ==", "workspaces": [ "parser", "example", diff --git a/package.json b/package.json index baf05e92111b..07ddc3ad6371 100644 --- a/package.json +++ b/package.json @@ -66,7 +66,7 @@ }, "dependencies": { "@dotlottie/react-player": "^1.6.3", - "@expensify/react-native-live-markdown": "0.1.143", + "@expensify/react-native-live-markdown": "0.1.163", "@expo/metro-runtime": "~3.2.3", "@firebase/app": "^0.10.10", "@firebase/performance": "^0.6.8", From cde40ee4ab1c32eac4d2b2187807a4f876de502f Mon Sep 17 00:00:00 2001 From: VickyStash Date: Fri, 4 Oct 2024 10:01:19 +0200 Subject: [PATCH 30/33] Revert "Update react-native-live-markdown version" This reverts commit 9a4883bc82242ce848acfaea976d99ce7f32660c. --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 87e6d11c5829..cf9978bae510 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "license": "MIT", "dependencies": { "@dotlottie/react-player": "^1.6.3", - "@expensify/react-native-live-markdown": "0.1.163", + "@expensify/react-native-live-markdown": "0.1.143", "@expo/metro-runtime": "~3.2.3", "@firebase/app": "^0.10.10", "@firebase/performance": "^0.6.8", @@ -3634,9 +3634,9 @@ } }, "node_modules/@expensify/react-native-live-markdown": { - "version": "0.1.163", - "resolved": "https://registry.npmjs.org/@expensify/react-native-live-markdown/-/react-native-live-markdown-0.1.163.tgz", - "integrity": "sha512-kIVWxKPHbXrLJ28TmI4sOndFjo8LktoytSiea4tS/GhVQXkbzZdtyTzNVfrQPSsJq+ITUbg701aC5XNqDhIAnQ==", + "version": "0.1.143", + "resolved": "https://registry.npmjs.org/@expensify/react-native-live-markdown/-/react-native-live-markdown-0.1.143.tgz", + "integrity": "sha512-hZXYjKyTl/b2p7Ig9qhoB7cfVtTTcoE2cWvea8NJT3f5ZYckdyHDAgHI4pg0S0N68jP205Sk5pzqlltZUpZk5w==", "workspaces": [ "parser", "example", diff --git a/package.json b/package.json index 07ddc3ad6371..baf05e92111b 100644 --- a/package.json +++ b/package.json @@ -66,7 +66,7 @@ }, "dependencies": { "@dotlottie/react-player": "^1.6.3", - "@expensify/react-native-live-markdown": "0.1.163", + "@expensify/react-native-live-markdown": "0.1.143", "@expo/metro-runtime": "~3.2.3", "@firebase/app": "^0.10.10", "@firebase/performance": "^0.6.8", From 592dc56b262f3cb85098d6a30cb9da7015f125b4 Mon Sep 17 00:00:00 2001 From: VickyStash Date: Sun, 13 Oct 2024 14:41:40 +0200 Subject: [PATCH 31/33] Add keys to get rid of lint errors --- src/components/AccountSwitcher.tsx | 14 +++++++++++++- .../TextWithTooltip/index.native.tsx | 14 +++++++++++++- .../index.native.tsx | 14 ++++++++++++-- .../index.native.tsx | 14 +++++++++++++- .../index.tsx | 16 +++++++++++++++- .../TextWithEmojiFragment/index.native.tsx | 7 +++++-- .../comment/TextWithEmojiFragment/index.tsx | 18 +++++++++++++++++- 7 files changed, 88 insertions(+), 9 deletions(-) diff --git a/src/components/AccountSwitcher.tsx b/src/components/AccountSwitcher.tsx index 207f77b7ee24..12932c58bbc3 100644 --- a/src/components/AccountSwitcher.tsx +++ b/src/components/AccountSwitcher.tsx @@ -153,7 +153,19 @@ function AccountSwitcher() { style={[styles.textBold, styles.textLarge, styles.flexShrink1]} > {processedTextArray.length !== 0 - ? processedTextArray.map(({text, isEmoji}) => (isEmoji ? {text} : text)) + ? processedTextArray.map(({text, isEmoji}, index) => + isEmoji ? ( + + {text} + + ) : ( + text + ), + ) : currentUserPersonalDetails?.displayName} {canSwitchAccounts && ( diff --git a/src/components/TextWithTooltip/index.native.tsx b/src/components/TextWithTooltip/index.native.tsx index 892b34649d93..7084156ec7de 100644 --- a/src/components/TextWithTooltip/index.native.tsx +++ b/src/components/TextWithTooltip/index.native.tsx @@ -14,7 +14,19 @@ function TextWithTooltip({text, style, numberOfLines = 1}: TextWithTooltipProps) numberOfLines={numberOfLines} > {processedTextArray.length !== 0 - ? processedTextArray.map(({text: textItem, isEmoji}) => (isEmoji ? {textItem} : textItem)) + ? processedTextArray.map(({text: textItem, isEmoji}, index) => + isEmoji ? ( + + {textItem} + + ) : ( + textItem + ), + ) : text} ); diff --git a/src/components/WorkspacesListRowDisplayName/index.native.tsx b/src/components/WorkspacesListRowDisplayName/index.native.tsx index e9db04c18aae..a5d017cc69a7 100644 --- a/src/components/WorkspacesListRowDisplayName/index.native.tsx +++ b/src/components/WorkspacesListRowDisplayName/index.native.tsx @@ -14,8 +14,18 @@ function WorkspacesListRowDisplayName({isDeleted, ownerName}: WorkspacesListRowD style={[styles.labelStrong, isDeleted ? styles.offlineFeedback.deleted : {}]} > {processedOwnerName.length !== 0 - ? processedOwnerName.map(({text, isEmoji}) => - isEmoji ? {text} : text, + ? processedOwnerName.map(({text, isEmoji}, index) => + isEmoji ? ( + + {text} + + ) : ( + text + ), ) : ownerName} diff --git a/src/pages/home/report/ReportActionItemMessageHeaderSender/index.native.tsx b/src/pages/home/report/ReportActionItemMessageHeaderSender/index.native.tsx index f4fa8285eb42..849174f6c9a0 100644 --- a/src/pages/home/report/ReportActionItemMessageHeaderSender/index.native.tsx +++ b/src/pages/home/report/ReportActionItemMessageHeaderSender/index.native.tsx @@ -20,7 +20,19 @@ function ReportActionItemMessageHeaderSender({fragmentText, accountID, delegateA style={[styles.chatItemMessageHeaderSender, isSingleLine ? styles.pre : styles.preWrap, styles.dFlex]} > {processedTextArray.length !== 0 - ? processedTextArray.map(({text, isEmoji}) => (isEmoji ? {text} : text)) + ? processedTextArray.map(({text, isEmoji}, index) => + isEmoji ? ( + + {text} + + ) : ( + text + ), + ) : fragmentText} diff --git a/src/pages/home/report/ReportActionItemMessageHeaderSender/index.tsx b/src/pages/home/report/ReportActionItemMessageHeaderSender/index.tsx index d2bedbd3f18b..869c550647ee 100644 --- a/src/pages/home/report/ReportActionItemMessageHeaderSender/index.tsx +++ b/src/pages/home/report/ReportActionItemMessageHeaderSender/index.tsx @@ -19,7 +19,21 @@ function ReportActionItemMessageHeaderSender({fragmentText, accountID, delegateA numberOfLines={isSingleLine ? 1 : undefined} style={[styles.chatItemMessageHeaderSender, isSingleLine ? styles.pre : styles.preWrap]} > - {processedTextArray.length !== 0 ? processedTextArray.map(({text, isEmoji}) => (isEmoji ? {text} : text)) : fragmentText} + {processedTextArray.length !== 0 + ? processedTextArray.map(({text, isEmoji}, index) => + isEmoji ? ( + + {text} + + ) : ( + text + ), + ) + : fragmentText}
); diff --git a/src/pages/home/report/comment/TextWithEmojiFragment/index.native.tsx b/src/pages/home/report/comment/TextWithEmojiFragment/index.native.tsx index f4efeefc6623..538ca4e9deb6 100644 --- a/src/pages/home/report/comment/TextWithEmojiFragment/index.native.tsx +++ b/src/pages/home/report/comment/TextWithEmojiFragment/index.native.tsx @@ -12,9 +12,12 @@ function TextWithEmojiFragment({message = '', style}: TextWithEmojiFragmentProps return ( - {processedTextArray.map(({text, isEmoji}) => + {processedTextArray.map(({text, isEmoji}, index) => isEmoji ? ( - + {text} ) : ( diff --git a/src/pages/home/report/comment/TextWithEmojiFragment/index.tsx b/src/pages/home/report/comment/TextWithEmojiFragment/index.tsx index e21a53451f2b..d19725da766d 100644 --- a/src/pages/home/report/comment/TextWithEmojiFragment/index.tsx +++ b/src/pages/home/report/comment/TextWithEmojiFragment/index.tsx @@ -9,7 +9,23 @@ function TextWithEmojiFragment({message = '', style}: TextWithEmojiFragmentProps const styles = useThemeStyles(); const processedTextArray = useMemo(() => EmojiUtils.splitTextWithEmojis(message), [message]); - return {processedTextArray.map(({text, isEmoji}) => (isEmoji ? {text} : convertToLTR(text)))}; + return ( + + {processedTextArray.map(({text, isEmoji}, index) => + isEmoji ? ( + + {text} + + ) : ( + convertToLTR(text) + ), + )} + + ); } TextWithEmojiFragment.displayName = 'TextWithEmojiFragment'; From 8010e02b37e62020480af5e109ab25e3bec5c8cc Mon Sep 17 00:00:00 2001 From: VickyStash Date: Sun, 13 Oct 2024 15:01:35 +0200 Subject: [PATCH 32/33] Clean up code duplicates --- src/components/AccountSwitcher.tsx | 14 +------------ .../TextWithTooltip/index.native.tsx | 16 +-------------- .../index.native.tsx | 14 +------------ src/libs/{EmojiUtils.ts => EmojiUtils.tsx} | 20 +++++++++++++++++++ .../index.native.tsx | 16 +-------------- .../index.tsx | 16 +-------------- 6 files changed, 25 insertions(+), 71 deletions(-) rename src/libs/{EmojiUtils.ts => EmojiUtils.tsx} (97%) diff --git a/src/components/AccountSwitcher.tsx b/src/components/AccountSwitcher.tsx index 12932c58bbc3..bbd7bb6a58b8 100644 --- a/src/components/AccountSwitcher.tsx +++ b/src/components/AccountSwitcher.tsx @@ -153,19 +153,7 @@ function AccountSwitcher() { style={[styles.textBold, styles.textLarge, styles.flexShrink1]} > {processedTextArray.length !== 0 - ? processedTextArray.map(({text, isEmoji}, index) => - isEmoji ? ( - - {text} - - ) : ( - text - ), - ) + ? EmojiUtils.getProcessedText(processedTextArray, styles.initialSettingsUsernameEmoji) : currentUserPersonalDetails?.displayName} {canSwitchAccounts && ( diff --git a/src/components/TextWithTooltip/index.native.tsx b/src/components/TextWithTooltip/index.native.tsx index 7084156ec7de..9f5f246ff9d3 100644 --- a/src/components/TextWithTooltip/index.native.tsx +++ b/src/components/TextWithTooltip/index.native.tsx @@ -13,21 +13,7 @@ function TextWithTooltip({text, style, numberOfLines = 1}: TextWithTooltipProps) style={style} numberOfLines={numberOfLines} > - {processedTextArray.length !== 0 - ? processedTextArray.map(({text: textItem, isEmoji}, index) => - isEmoji ? ( - - {textItem} - - ) : ( - textItem - ), - ) - : text} + {processedTextArray.length !== 0 ? EmojiUtils.getProcessedText(processedTextArray, [style, styles.emojisFontFamily]) : text} ); } diff --git a/src/components/WorkspacesListRowDisplayName/index.native.tsx b/src/components/WorkspacesListRowDisplayName/index.native.tsx index a5d017cc69a7..1a91e2857db3 100644 --- a/src/components/WorkspacesListRowDisplayName/index.native.tsx +++ b/src/components/WorkspacesListRowDisplayName/index.native.tsx @@ -14,19 +14,7 @@ function WorkspacesListRowDisplayName({isDeleted, ownerName}: WorkspacesListRowD style={[styles.labelStrong, isDeleted ? styles.offlineFeedback.deleted : {}]} > {processedOwnerName.length !== 0 - ? processedOwnerName.map(({text, isEmoji}, index) => - isEmoji ? ( - - {text} - - ) : ( - text - ), - ) + ? EmojiUtils.getProcessedText(processedOwnerName, [styles.labelStrong, isDeleted ? styles.offlineFeedback.deleted : {}, styles.emojisWithTextFontFamily]) : ownerName} ); diff --git a/src/libs/EmojiUtils.ts b/src/libs/EmojiUtils.tsx similarity index 97% rename from src/libs/EmojiUtils.ts rename to src/libs/EmojiUtils.tsx index 4aa777998d2a..9974fdb30477 100644 --- a/src/libs/EmojiUtils.ts +++ b/src/libs/EmojiUtils.tsx @@ -1,8 +1,11 @@ import {Str} from 'expensify-common'; +import React from 'react'; +import type {StyleProp, TextStyle} from 'react-native'; import Onyx from 'react-native-onyx'; import type {OnyxEntry} from 'react-native-onyx'; import * as Emojis from '@assets/emojis'; import type {Emoji, HeaderEmoji, PickerEmojis} from '@assets/emojis/types'; +import Text from '@components/Text'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type {FrequentlyUsedEmoji, Locale} from '@src/types/onyx'; @@ -652,6 +655,22 @@ function splitTextWithEmojis(text = ''): TextWithEmoji[] { return splitText; } +function getProcessedText(processedTextArray: TextWithEmoji[], style: StyleProp): Array { + return processedTextArray.map(({text, isEmoji}, index) => + isEmoji ? ( + + {text} + + ) : ( + text + ), + ); +} + export type {HeaderIndice, EmojiPickerList, EmojiSpacer, EmojiPickerListItem}; export { @@ -659,6 +678,7 @@ export { findEmojiByCode, getEmojiName, getLocalizedEmojiName, + getProcessedText, getHeaderEmojis, mergeEmojisWithFrequentlyUsedEmojis, containsOnlyEmojis, diff --git a/src/pages/home/report/ReportActionItemMessageHeaderSender/index.native.tsx b/src/pages/home/report/ReportActionItemMessageHeaderSender/index.native.tsx index 849174f6c9a0..9a752c3a9007 100644 --- a/src/pages/home/report/ReportActionItemMessageHeaderSender/index.native.tsx +++ b/src/pages/home/report/ReportActionItemMessageHeaderSender/index.native.tsx @@ -19,21 +19,7 @@ function ReportActionItemMessageHeaderSender({fragmentText, accountID, delegateA numberOfLines={isSingleLine ? 1 : undefined} style={[styles.chatItemMessageHeaderSender, isSingleLine ? styles.pre : styles.preWrap, styles.dFlex]} > - {processedTextArray.length !== 0 - ? processedTextArray.map(({text, isEmoji}, index) => - isEmoji ? ( - - {text} - - ) : ( - text - ), - ) - : fragmentText} + {processedTextArray.length !== 0 ? EmojiUtils.getProcessedText(processedTextArray, [styles.emojisWithTextFontSize, styles.emojisWithTextFontFamily]) : fragmentText} ); diff --git a/src/pages/home/report/ReportActionItemMessageHeaderSender/index.tsx b/src/pages/home/report/ReportActionItemMessageHeaderSender/index.tsx index 869c550647ee..d5602dbedfae 100644 --- a/src/pages/home/report/ReportActionItemMessageHeaderSender/index.tsx +++ b/src/pages/home/report/ReportActionItemMessageHeaderSender/index.tsx @@ -19,21 +19,7 @@ function ReportActionItemMessageHeaderSender({fragmentText, accountID, delegateA numberOfLines={isSingleLine ? 1 : undefined} style={[styles.chatItemMessageHeaderSender, isSingleLine ? styles.pre : styles.preWrap]} > - {processedTextArray.length !== 0 - ? processedTextArray.map(({text, isEmoji}, index) => - isEmoji ? ( - - {text} - - ) : ( - text - ), - ) - : fragmentText} + {processedTextArray.length !== 0 ? EmojiUtils.getProcessedText(processedTextArray, styles.emojisWithTextFontSize) : fragmentText} ); From 0c14e8759de853b483bf22ce1bfc1bd379b2fc3a Mon Sep 17 00:00:00 2001 From: VickyStash Date: Wed, 16 Oct 2024 11:41:51 +0300 Subject: [PATCH 33/33] Reapply changes after merging main --- src/components/Composer/implementation/index.tsx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/components/Composer/implementation/index.tsx b/src/components/Composer/implementation/index.tsx index 4431007793cb..741467867c15 100755 --- a/src/components/Composer/implementation/index.tsx +++ b/src/components/Composer/implementation/index.tsx @@ -20,6 +20,7 @@ import updateIsFullComposerAvailable from '@libs/ComposerUtils/updateIsFullCompo import * as EmojiUtils from '@libs/EmojiUtils'; import * as FileUtils from '@libs/fileDownload/FileUtils'; import isEnterWhileComposition from '@libs/KeyboardShortcut/isEnterWhileComposition'; +import variables from '@styles/variables'; import CONST from '@src/CONST'; const excludeNoStyles: Array = []; @@ -72,6 +73,7 @@ function Composer( start: selectionProp.start, end: selectionProp.end, }); + const [hasMultipleLines, setHasMultipleLines] = useState(false); const [isRendered, setIsRendered] = useState(false); const isScrollBarVisible = useIsScrollBarVisible(textInput, value ?? ''); const [prevScroll, setPrevScroll] = useState(); @@ -330,10 +332,10 @@ function Composer( scrollStyleMemo, StyleUtils.getComposerMaxHeightStyle(maxLines, isComposerFullSize), isComposerFullSize ? {height: '100%', maxHeight: 'none'} : undefined, - textContainsOnlyEmojis ? styles.onlyEmojisTextLineHeight : {}, + textContainsOnlyEmojis && hasMultipleLines ? styles.onlyEmojisTextLineHeight : {}, ], - [style, styles.rtlTextRenderForSafari, styles.onlyEmojisTextLineHeight, scrollStyleMemo, StyleUtils, maxLines, isComposerFullSize, textContainsOnlyEmojis], + [style, styles.rtlTextRenderForSafari, styles.onlyEmojisTextLineHeight, scrollStyleMemo, hasMultipleLines, StyleUtils, maxLines, isComposerFullSize, textContainsOnlyEmojis], ); return ( @@ -353,6 +355,7 @@ function Composer( {...props} onSelectionChange={addCursorPositionToSelectionChange} onContentSizeChange={(e) => { + setHasMultipleLines(e.nativeEvent.contentSize.height > variables.componentSizeLarge); updateIsFullComposerAvailable({maxLines, isComposerFullSize, isDisabled, setIsFullComposerAvailable}, e, styles); }} disabled={isDisabled}