From 3b484a098bca87defe902835d0bee011a1d699a3 Mon Sep 17 00:00:00 2001 From: Mykhailo Kravchenko Date: Mon, 11 Dec 2023 18:02:40 +0100 Subject: [PATCH 1/8] add overflow wrap globally for hml text --- .../HTMLEngineProvider/BaseHTMLEngineProvider.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/components/HTMLEngineProvider/BaseHTMLEngineProvider.js b/src/components/HTMLEngineProvider/BaseHTMLEngineProvider.js index 8cddd3c017de..df95f18d0d0f 100755 --- a/src/components/HTMLEngineProvider/BaseHTMLEngineProvider.js +++ b/src/components/HTMLEngineProvider/BaseHTMLEngineProvider.js @@ -65,7 +65,17 @@ function BaseHTMLEngineProvider(props) { ); // We need to memoize this prop to make it referentially stable. - const defaultTextProps = useMemo(() => ({selectable: props.textSelectable, allowFontScaling: false, textBreakStrategy: 'simple'}), [props.textSelectable]); + const defaultTextProps = useMemo( + () => ({ + selectable: props.textSelectable, + allowFontScaling: false, + textBreakStrategy: 'simple', + style: { + overflowWrap: 'anywhere', + }, + }), + [props.textSelectable], + ); const defaultViewProps = {style: [styles.alignItemsStart, styles.userSelectText]}; return ( From a025a21e78e917e1b1be0c09bdf96b69e7b207d8 Mon Sep 17 00:00:00 2001 From: Mykhailo Kravchenko Date: Tue, 12 Dec 2023 11:07:00 +0100 Subject: [PATCH 2/8] complete long email wrapping fix --- .../BaseHTMLEngineProvider.js | 13 ++---------- .../HTMLRenderers/NextStepsEmailRenderer.js | 21 +++++++++++++++++++ .../HTMLEngineProvider/HTMLRenderers/index.js | 2 ++ src/libs/NextStepUtils.ts | 9 +++++++- src/styles/utilities/overflow.ts | 4 ++++ 5 files changed, 37 insertions(+), 12 deletions(-) create mode 100644 src/components/HTMLEngineProvider/HTMLRenderers/NextStepsEmailRenderer.js diff --git a/src/components/HTMLEngineProvider/BaseHTMLEngineProvider.js b/src/components/HTMLEngineProvider/BaseHTMLEngineProvider.js index df95f18d0d0f..4a10e94f4b6d 100755 --- a/src/components/HTMLEngineProvider/BaseHTMLEngineProvider.js +++ b/src/components/HTMLEngineProvider/BaseHTMLEngineProvider.js @@ -60,22 +60,13 @@ function BaseHTMLEngineProvider(props) { }), 'mention-user': defaultHTMLElementModels.span.extend({tagName: 'mention-user'}), 'mention-here': defaultHTMLElementModels.span.extend({tagName: 'mention-here'}), + 'next-steps-email': defaultHTMLElementModels.span.extend({tagName: 'next-steps-email'}), }), [styles.colorMuted, styles.formError, styles.mb0], ); // We need to memoize this prop to make it referentially stable. - const defaultTextProps = useMemo( - () => ({ - selectable: props.textSelectable, - allowFontScaling: false, - textBreakStrategy: 'simple', - style: { - overflowWrap: 'anywhere', - }, - }), - [props.textSelectable], - ); + const defaultTextProps = useMemo(() => ({selectable: props.textSelectable, allowFontScaling: false, textBreakStrategy: 'simple'}), [props.textSelectable]); const defaultViewProps = {style: [styles.alignItemsStart, styles.userSelectText]}; return ( diff --git a/src/components/HTMLEngineProvider/HTMLRenderers/NextStepsEmailRenderer.js b/src/components/HTMLEngineProvider/HTMLRenderers/NextStepsEmailRenderer.js new file mode 100644 index 000000000000..0646037a9436 --- /dev/null +++ b/src/components/HTMLEngineProvider/HTMLRenderers/NextStepsEmailRenderer.js @@ -0,0 +1,21 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import Text from '@components/Text'; +import useThemeStyles from '@styles/useThemeStyles'; + +const propTypes = { + tnode: PropTypes.shape({ + data: PropTypes.string.isRequired, + }).isRequired, +}; + +function NextStepsEmailRenderer({tnode}) { + const styles = useThemeStyles(); + + return {tnode.data}; +} + +NextStepsEmailRenderer.propTypes = propTypes; +NextStepsEmailRenderer.displayName = 'NextStepsEmailRenderer'; + +export default NextStepsEmailRenderer; diff --git a/src/components/HTMLEngineProvider/HTMLRenderers/index.js b/src/components/HTMLEngineProvider/HTMLRenderers/index.js index 69f8eeac798e..45a9ce893d9f 100644 --- a/src/components/HTMLEngineProvider/HTMLRenderers/index.js +++ b/src/components/HTMLEngineProvider/HTMLRenderers/index.js @@ -4,6 +4,7 @@ import EditedRenderer from './EditedRenderer'; import ImageRenderer from './ImageRenderer'; import MentionHereRenderer from './MentionHereRenderer'; import MentionUserRenderer from './MentionUserRenderer'; +import NextStepsEmailRenderer from './NextStepsEmailRenderer'; import PreRenderer from './PreRenderer'; /** @@ -20,4 +21,5 @@ export default { pre: PreRenderer, 'mention-user': MentionUserRenderer, 'mention-here': MentionHereRenderer, + 'next-steps-email': NextStepsEmailRenderer, }; diff --git a/src/libs/NextStepUtils.ts b/src/libs/NextStepUtils.ts index 538e8dbe81f0..0fa7fe451d7b 100644 --- a/src/libs/NextStepUtils.ts +++ b/src/libs/NextStepUtils.ts @@ -11,7 +11,14 @@ function parseMessage(messages: Message[] | undefined) { messages?.forEach((part) => { // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing const tagType = part.type || 'span'; - nextStepHTML += `<${tagType}>${Str.safeEscape(part.text)}`; + const isEmail = Str.isValidEmail(part.text); + let content = Str.safeEscape(part.text); + + if (isEmail) { + content = `${content}`; + } + + nextStepHTML += `<${tagType}>${content}`; }); return nextStepHTML diff --git a/src/styles/utilities/overflow.ts b/src/styles/utilities/overflow.ts index 9b4fa010af84..9e700c344991 100644 --- a/src/styles/utilities/overflow.ts +++ b/src/styles/utilities/overflow.ts @@ -24,6 +24,10 @@ export default { overscrollBehaviorX: 'none', }, + overflowWrapAnywhere: { + overflowWrap: 'anywhere', + }, + overscrollBehaviorContain, overflowAuto, From 9d1520b4dfc8f0852aa699b17c9ed10adda4afa6 Mon Sep 17 00:00:00 2001 From: Mykhailo Kravchenko Date: Tue, 12 Dec 2023 11:39:31 +0100 Subject: [PATCH 3/8] combine with next-steps --- .../HTMLRenderers/NextStepsEmailRenderer.js | 2 +- src/libs/NextStepUtils.ts | 11 +++-------- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/src/components/HTMLEngineProvider/HTMLRenderers/NextStepsEmailRenderer.js b/src/components/HTMLEngineProvider/HTMLRenderers/NextStepsEmailRenderer.js index 0646037a9436..b3baf7c9af16 100644 --- a/src/components/HTMLEngineProvider/HTMLRenderers/NextStepsEmailRenderer.js +++ b/src/components/HTMLEngineProvider/HTMLRenderers/NextStepsEmailRenderer.js @@ -12,7 +12,7 @@ const propTypes = { function NextStepsEmailRenderer({tnode}) { const styles = useThemeStyles(); - return {tnode.data}; + return {tnode.data}; } NextStepsEmailRenderer.propTypes = propTypes; diff --git a/src/libs/NextStepUtils.ts b/src/libs/NextStepUtils.ts index 1847a57c6771..3d662f6cdf01 100644 --- a/src/libs/NextStepUtils.ts +++ b/src/libs/NextStepUtils.ts @@ -9,16 +9,11 @@ function parseMessage(messages: Message[] | undefined) { let nextStepHTML = ''; messages?.forEach((part) => { - // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing - const tagType = part.type || 'span'; const isEmail = Str.isValidEmail(part.text); - let content = Str.safeEscape(part.text); - - if (isEmail) { - content = `${content}`; - } + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing + const tagType = isEmail ? 'next-steps-email' : part.type || 'span'; - nextStepHTML += `<${tagType}>${content}`; + nextStepHTML += `<${tagType}>${Str.safeEscape(part.text)}`; }); const formattedHtml = nextStepHTML From 188a9157a9c82426e103b784c92f240aa1bbb4f5 Mon Sep 17 00:00:00 2001 From: Mykhailo Kravchenko Date: Tue, 12 Dec 2023 15:09:59 +0100 Subject: [PATCH 4/8] use wordBreak instead of --- .../HTMLRenderers/NextStepsEmailRenderer.js | 2 +- src/styles/utilities/overflow.ts | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/components/HTMLEngineProvider/HTMLRenderers/NextStepsEmailRenderer.js b/src/components/HTMLEngineProvider/HTMLRenderers/NextStepsEmailRenderer.js index b3baf7c9af16..2a2452b9c6d5 100644 --- a/src/components/HTMLEngineProvider/HTMLRenderers/NextStepsEmailRenderer.js +++ b/src/components/HTMLEngineProvider/HTMLRenderers/NextStepsEmailRenderer.js @@ -12,7 +12,7 @@ const propTypes = { function NextStepsEmailRenderer({tnode}) { const styles = useThemeStyles(); - return {tnode.data}; + return {tnode.data}; } NextStepsEmailRenderer.propTypes = propTypes; diff --git a/src/styles/utilities/overflow.ts b/src/styles/utilities/overflow.ts index 9e700c344991..9b4fa010af84 100644 --- a/src/styles/utilities/overflow.ts +++ b/src/styles/utilities/overflow.ts @@ -24,10 +24,6 @@ export default { overscrollBehaviorX: 'none', }, - overflowWrapAnywhere: { - overflowWrap: 'anywhere', - }, - overscrollBehaviorContain, overflowAuto, From 5aab8b38c67e6482cefc3d329c326b91139417da Mon Sep 17 00:00:00 2001 From: Mykhailo Kravchenko Date: Thu, 14 Dec 2023 16:06:42 +0100 Subject: [PATCH 5/8] use one more email utils --- .../HTMLRenderers/NextStepsEmailRenderer.js | 4 ++-- src/libs/NextStepUtils.ts | 11 +++++++++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/components/HTMLEngineProvider/HTMLRenderers/NextStepsEmailRenderer.js b/src/components/HTMLEngineProvider/HTMLRenderers/NextStepsEmailRenderer.js index 2a2452b9c6d5..a2cd5f11ed64 100644 --- a/src/components/HTMLEngineProvider/HTMLRenderers/NextStepsEmailRenderer.js +++ b/src/components/HTMLEngineProvider/HTMLRenderers/NextStepsEmailRenderer.js @@ -1,7 +1,7 @@ import PropTypes from 'prop-types'; import React from 'react'; import Text from '@components/Text'; -import useThemeStyles from '@styles/useThemeStyles'; +import useThemeStyles from '@hooks/useThemeStyles'; const propTypes = { tnode: PropTypes.shape({ @@ -12,7 +12,7 @@ const propTypes = { function NextStepsEmailRenderer({tnode}) { const styles = useThemeStyles(); - return {tnode.data}; + return {tnode.data}; } NextStepsEmailRenderer.propTypes = propTypes; diff --git a/src/libs/NextStepUtils.ts b/src/libs/NextStepUtils.ts index 7e81bec5f7c8..f5f18612a5a5 100644 --- a/src/libs/NextStepUtils.ts +++ b/src/libs/NextStepUtils.ts @@ -1,4 +1,5 @@ import Str from 'expensify-common/lib/str'; +import EmailUtils from './EmailUtils'; type Message = { text: string; @@ -11,9 +12,15 @@ function parseMessage(messages: Message[] | undefined) { messages?.forEach((part) => { const isEmail = Str.isValidEmail(part.text); // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing - const tagType = isEmail ? 'next-steps-email' : part.type || 'span'; + let tagType = part.type || 'span'; + let content = Str.safeEscape(part.text); - nextStepHTML += `<${tagType}>${Str.safeEscape(part.text)}`; + if (isEmail) { + tagType = 'next-steps-email'; + content = EmailUtils.prefixMailSeparatorsWithBreakOpportunities(content); + } + + nextStepHTML += `<${tagType}>${content}`; }); const formattedHtml = nextStepHTML From 858e6ed036c860896c1bc4bacb072a2073a47de1 Mon Sep 17 00:00:00 2001 From: Mykhailo Kravchenko Date: Mon, 18 Dec 2023 11:45:29 +0100 Subject: [PATCH 6/8] migrate to TS --- ...sEmailRenderer.js => NextStepsEmailRenderer.tsx} | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) rename src/components/HTMLEngineProvider/HTMLRenderers/{NextStepsEmailRenderer.js => NextStepsEmailRenderer.tsx} (61%) diff --git a/src/components/HTMLEngineProvider/HTMLRenderers/NextStepsEmailRenderer.js b/src/components/HTMLEngineProvider/HTMLRenderers/NextStepsEmailRenderer.tsx similarity index 61% rename from src/components/HTMLEngineProvider/HTMLRenderers/NextStepsEmailRenderer.js rename to src/components/HTMLEngineProvider/HTMLRenderers/NextStepsEmailRenderer.tsx index a2cd5f11ed64..15eb93d4ed2e 100644 --- a/src/components/HTMLEngineProvider/HTMLRenderers/NextStepsEmailRenderer.js +++ b/src/components/HTMLEngineProvider/HTMLRenderers/NextStepsEmailRenderer.tsx @@ -1,21 +1,20 @@ -import PropTypes from 'prop-types'; import React from 'react'; import Text from '@components/Text'; import useThemeStyles from '@hooks/useThemeStyles'; -const propTypes = { - tnode: PropTypes.shape({ - data: PropTypes.string.isRequired, - }).isRequired, +type NextStepsEmailRendererProps = { + tnode: { + data: string; + }; }; -function NextStepsEmailRenderer({tnode}) { +function NextStepsEmailRenderer({tnode}: NextStepsEmailRendererProps) { const styles = useThemeStyles(); return {tnode.data}; } -NextStepsEmailRenderer.propTypes = propTypes; NextStepsEmailRenderer.displayName = 'NextStepsEmailRenderer'; export default NextStepsEmailRenderer; +export type {NextStepsEmailRendererProps}; From d601867eb7dfa49579a05accc853265a3ab2561f Mon Sep 17 00:00:00 2001 From: Mykhailo Kravchenko Date: Mon, 18 Dec 2023 14:05:48 +0100 Subject: [PATCH 7/8] do not export type --- .../HTMLEngineProvider/HTMLRenderers/NextStepsEmailRenderer.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/HTMLEngineProvider/HTMLRenderers/NextStepsEmailRenderer.tsx b/src/components/HTMLEngineProvider/HTMLRenderers/NextStepsEmailRenderer.tsx index 15eb93d4ed2e..c5d3a15a30e2 100644 --- a/src/components/HTMLEngineProvider/HTMLRenderers/NextStepsEmailRenderer.tsx +++ b/src/components/HTMLEngineProvider/HTMLRenderers/NextStepsEmailRenderer.tsx @@ -17,4 +17,3 @@ function NextStepsEmailRenderer({tnode}: NextStepsEmailRendererProps) { NextStepsEmailRenderer.displayName = 'NextStepsEmailRenderer'; export default NextStepsEmailRenderer; -export type {NextStepsEmailRendererProps}; From fadfcf4ad4e42bf3b5d0e4ed877bcda85b5c75ea Mon Sep 17 00:00:00 2001 From: Mykhailo Kravchenko Date: Mon, 18 Dec 2023 15:43:47 +0100 Subject: [PATCH 8/8] use nullish operator --- src/libs/NextStepUtils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/NextStepUtils.ts b/src/libs/NextStepUtils.ts index f5f18612a5a5..ebad204a29a3 100644 --- a/src/libs/NextStepUtils.ts +++ b/src/libs/NextStepUtils.ts @@ -12,7 +12,7 @@ function parseMessage(messages: Message[] | undefined) { messages?.forEach((part) => { const isEmail = Str.isValidEmail(part.text); // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing - let tagType = part.type || 'span'; + let tagType = part.type ?? 'span'; let content = Str.safeEscape(part.text); if (isEmail) {