diff --git a/src/components/HTMLEngineProvider/HTMLRenderers/EditedRenderer.js b/src/components/HTMLEngineProvider/HTMLRenderers/EditedRenderer.js index 262a4d1f178e..a0b6b0dadf9f 100644 --- a/src/components/HTMLEngineProvider/HTMLRenderers/EditedRenderer.js +++ b/src/components/HTMLEngineProvider/HTMLRenderers/EditedRenderer.js @@ -18,22 +18,23 @@ function EditedRenderer(props) { const defaultRendererProps = _.omit(props, ['TDefaultRenderer', 'style', 'tnode']); const isPendingDelete = Boolean(props.tnode.attributes.deleted !== undefined); return ( - - {/* Native devices do not support margin between nested text */} + {' '} - {props.translate('reportActionCompose.edited')} + + {props.translate('reportActionCompose.edited')} + ); } diff --git a/src/components/HTMLEngineProvider/applyStrikethrough/index.js b/src/components/HTMLEngineProvider/applyStrikethrough/index.js deleted file mode 100644 index b754a37dbde9..000000000000 --- a/src/components/HTMLEngineProvider/applyStrikethrough/index.js +++ /dev/null @@ -1,5 +0,0 @@ -function applyStrikethrough(html) { - return html; -} - -export default applyStrikethrough; diff --git a/src/components/HTMLEngineProvider/applyStrikethrough/index.native.js b/src/components/HTMLEngineProvider/applyStrikethrough/index.native.js deleted file mode 100644 index 266e4eb20f62..000000000000 --- a/src/components/HTMLEngineProvider/applyStrikethrough/index.native.js +++ /dev/null @@ -1,8 +0,0 @@ -function applyStrikethrough(html, isPendingDelete) { - if (isPendingDelete) { - return `${html}`; - } - return html; -} - -export default applyStrikethrough; diff --git a/src/components/OfflineWithFeedback.js b/src/components/OfflineWithFeedback.js index fb0411d24f4c..dae170dd1d5c 100644 --- a/src/components/OfflineWithFeedback.js +++ b/src/components/OfflineWithFeedback.js @@ -2,11 +2,7 @@ import _ from 'underscore'; import React from 'react'; import {View} from 'react-native'; import PropTypes from 'prop-types'; -import compose from '../libs/compose'; -import withLocalize, {withLocalizePropTypes} from './withLocalize'; -import {withNetwork} from './OnyxProvider'; import CONST from '../CONST'; -import networkPropTypes from './networkPropTypes'; import stylePropTypes from '../styles/stylePropTypes'; import styles from '../styles/styles'; import Tooltip from './Tooltip'; @@ -16,6 +12,8 @@ import * as StyleUtils from '../styles/StyleUtils'; import DotIndicatorMessage from './DotIndicatorMessage'; import shouldRenderOffscreen from '../libs/shouldRenderOffscreen'; import PressableWithoutFeedback from './Pressable/PressableWithoutFeedback'; +import useLocalize from '../hooks/useLocalize'; +import useNetwork from '../hooks/useNetwork'; /** * This component should be used when we are using the offline pattern B (offline with feedback). @@ -46,9 +44,6 @@ const propTypes = { /** The content that needs offline feedback */ children: PropTypes.node.isRequired, - /** Information about the network */ - network: networkPropTypes.isRequired, - /** Additional styles to add after local styles. Applied to the parent container */ style: stylePropTypes, @@ -58,7 +53,11 @@ const propTypes = { /** Additional style object for the error row */ errorRowStyles: stylePropTypes, - ...withLocalizePropTypes, + /** Whether applying strikethrough to the children should be disabled */ + shouldDisableStrikeThrough: PropTypes.bool, + + /** Whether to apply needsOffscreenAlphaCompositing prop to the children */ + needsOffscreenAlphaCompositing: PropTypes.bool, }; const defaultProps = { @@ -71,6 +70,8 @@ const defaultProps = { style: [], contentContainerStyle: [], errorRowStyles: [], + shouldDisableStrikeThrough: false, + needsOffscreenAlphaCompositing: false, }; /** @@ -92,17 +93,20 @@ function applyStrikeThrough(children) { } function OfflineWithFeedback(props) { + const {translate} = useLocalize(); + const {isOffline} = useNetwork(); + const hasErrors = !_.isEmpty(props.errors); // Some errors have a null message. This is used to apply opacity only and to avoid showing redundant messages. const errorMessages = _.omit(props.errors, (e) => e === null); const hasErrorMessages = !_.isEmpty(errorMessages); - const isOfflinePendingAction = props.network.isOffline && props.pendingAction; + const isOfflinePendingAction = isOffline && props.pendingAction; const isUpdateOrDeleteError = hasErrors && (props.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE || props.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE); const isAddError = hasErrors && props.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD; const needsOpacity = !props.shouldDisableOpacity && ((isOfflinePendingAction && !isUpdateOrDeleteError) || isAddError); - const needsStrikeThrough = props.network.isOffline && props.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE; - const hideChildren = props.shouldHideOnDelete && !props.network.isOffline && props.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE && !hasErrors; + const needsStrikeThrough = !props.shouldDisableStrikeThrough && isOffline && props.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE; + const hideChildren = props.shouldHideOnDelete && !isOffline && props.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE && !hasErrors; let children = props.children; // Apply strikethrough to children if needed, but skip it if we are not going to render them @@ -126,12 +130,12 @@ function OfflineWithFeedback(props) { messages={errorMessages} type="error" /> - + @@ -146,4 +150,4 @@ OfflineWithFeedback.propTypes = propTypes; OfflineWithFeedback.defaultProps = defaultProps; OfflineWithFeedback.displayName = 'OfflineWithFeedback'; -export default compose(withLocalize, withNetwork())(OfflineWithFeedback); +export default OfflineWithFeedback; diff --git a/src/pages/home/report/ReportActionItem.js b/src/pages/home/report/ReportActionItem.js index f696976eb0b4..7440b28a8b3b 100644 --- a/src/pages/home/report/ReportActionItem.js +++ b/src/pages/home/report/ReportActionItem.js @@ -620,6 +620,7 @@ function ReportActionItem(props) { errors={props.action.errors} errorRowStyles={[styles.ml10, styles.mr2]} needsOffscreenAlphaCompositing={ReportActionsUtils.isMoneyRequestAction(props.action)} + shouldDisableStrikeThrough > {isWhisper && ( diff --git a/src/pages/home/report/ReportActionItemFragment.js b/src/pages/home/report/ReportActionItemFragment.js index e9fd30f5b057..1f61b44841bc 100644 --- a/src/pages/home/report/ReportActionItemFragment.js +++ b/src/pages/home/report/ReportActionItemFragment.js @@ -16,7 +16,6 @@ import compose from '../../../libs/compose'; import convertToLTR from '../../../libs/convertToLTR'; import {withNetwork} from '../../../components/OnyxProvider'; import CONST from '../../../CONST'; -import applyStrikethrough from '../../../components/HTMLEngineProvider/applyStrikethrough'; import editedLabelStyles from '../../../styles/editedLabelStyles'; import UserDetailsTooltip from '../../../components/UserDetailsTooltip'; import avatarPropTypes from '../../../components/avatarPropTypes'; @@ -112,6 +111,7 @@ function ReportActionItemFragment(props) { ); } const {html, text} = props.fragment; + const isPendingDelete = props.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE && props.network.isOffline; // Threaded messages display "[Deleted message]" instead of being hidden altogether. // While offline we display the previous message with a strikethrough style. Once online we want to @@ -128,35 +128,40 @@ function ReportActionItemFragment(props) { // Only render HTML if we have html in the fragment if (!differByLineBreaksOnly) { - const isPendingDelete = props.pendingAction === CONST.RED_BRICK_ROAD_PENDING_ACTION.DELETE && props.network.isOffline; const editedTag = props.fragment.isEdited ? `` : ''; - const htmlContent = applyStrikethrough(html + editedTag, isPendingDelete); + const htmlContent = isPendingDelete ? `${html}` : html; - return ${htmlContent}` : `${htmlContent}`} />; + const htmlWithTag = editedTag ? `${htmlContent}${editedTag}` : htmlContent; + + return ${htmlWithTag}` : `${htmlWithTag}`} />; } const containsOnlyEmojis = EmojiUtils.containsOnlyEmojis(text); return ( - - {convertToLTR(props.iouMessage || text)} + + + {convertToLTR(props.iouMessage || text)} + {Boolean(props.fragment.isEdited) && ( - + <> {' '} - {props.translate('reportActionCompose.edited')} - + + {props.translate('reportActionCompose.edited')} + + )} ); diff --git a/src/styles/styles.js b/src/styles/styles.js index ef69eed9c6b6..c86ca2cb8399 100644 --- a/src/styles/styles.js +++ b/src/styles/styles.js @@ -80,6 +80,7 @@ const webViewStyles = (theme) => ({ del: { textDecorationLine: 'line-through', textDecorationStyle: 'solid', + flex: 1, }, strong: { diff --git a/tests/perf-test/SelectionList.perf-test.js b/tests/perf-test/SelectionList.perf-test.js index 2d9cd4a87829..cdf9492e0ff3 100644 --- a/tests/perf-test/SelectionList.perf-test.js +++ b/tests/perf-test/SelectionList.perf-test.js @@ -21,6 +21,12 @@ jest.mock('../../src/components/withLocalize', () => (Component) => (props) => ( /> )); +jest.mock('../../src/hooks/useNetwork', () => + jest.fn(() => ({ + isOffline: false, + })), +); + jest.mock('../../src/components/withKeyboardState', () => (Component) => (props) => (