forked from Expensify/App
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request Expensify#25524 from cubuspl42/fix-name-jump-1
Refactor comment message rendering
- Loading branch information
Showing
6 changed files
with
208 additions
and
67 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
33 changes: 33 additions & 0 deletions
33
src/pages/home/report/comment/AttachmentCommentFragment.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import PropTypes from 'prop-types'; | ||
import React from 'react'; | ||
import {View} from 'react-native'; | ||
import reportActionSourcePropType from '@pages/home/report/reportActionSourcePropType'; | ||
import styles from '@styles/styles'; | ||
import RenderCommentHTML from './RenderCommentHTML'; | ||
|
||
const propTypes = { | ||
/** The reportAction's source */ | ||
source: reportActionSourcePropType.isRequired, | ||
|
||
/** The message fragment's HTML */ | ||
html: PropTypes.string.isRequired, | ||
|
||
/** Should extra margin be added on top of the component? */ | ||
addExtraMargin: PropTypes.bool.isRequired, | ||
}; | ||
|
||
function AttachmentCommentFragment({addExtraMargin, html, source}) { | ||
return ( | ||
<View style={addExtraMargin ? styles.mt2 : {}}> | ||
<RenderCommentHTML | ||
source={source} | ||
html={html} | ||
/> | ||
</View> | ||
); | ||
} | ||
|
||
AttachmentCommentFragment.propTypes = propTypes; | ||
AttachmentCommentFragment.displayName = 'AttachmentCommentFragment'; | ||
|
||
export default AttachmentCommentFragment; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import PropTypes from 'prop-types'; | ||
import React from 'react'; | ||
import RenderHTML from '@components/RenderHTML'; | ||
import reportActionSourcePropType from '@pages/home/report/reportActionSourcePropType'; | ||
|
||
const propTypes = { | ||
/** The reportAction's source */ | ||
source: reportActionSourcePropType.isRequired, | ||
|
||
/** The comment's HTML */ | ||
html: PropTypes.string.isRequired, | ||
}; | ||
|
||
function RenderCommentHTML({html, source}) { | ||
const commentHtml = source === 'email' ? `<email-comment>${html}</email-comment>` : `<comment>${html}</comment>`; | ||
|
||
return <RenderHTML html={commentHtml} />; | ||
} | ||
|
||
RenderCommentHTML.propTypes = propTypes; | ||
RenderCommentHTML.displayName = 'RenderCommentHTML'; | ||
|
||
export default RenderCommentHTML; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
import Str from 'expensify-common/lib/str'; | ||
import PropTypes from 'prop-types'; | ||
import React, {memo} from 'react'; | ||
import Text from '@components/Text'; | ||
import withLocalize, {withLocalizePropTypes} from '@components/withLocalize'; | ||
import withWindowDimensions, {windowDimensionsPropTypes} from '@components/withWindowDimensions'; | ||
import ZeroWidthView from '@components/ZeroWidthView'; | ||
import compose from '@libs/compose'; | ||
import convertToLTR from '@libs/convertToLTR'; | ||
import * as DeviceCapabilities from '@libs/DeviceCapabilities'; | ||
import * as EmojiUtils from '@libs/EmojiUtils'; | ||
import reportActionFragmentPropTypes from '@pages/home/report/reportActionFragmentPropTypes'; | ||
import reportActionSourcePropType from '@pages/home/report/reportActionSourcePropType'; | ||
import editedLabelStyles from '@styles/editedLabelStyles'; | ||
import styles from '@styles/styles'; | ||
import themeColors from '@styles/themes/default'; | ||
import variables from '@styles/variables'; | ||
import CONST from '@src/CONST'; | ||
import RenderCommentHTML from './RenderCommentHTML'; | ||
|
||
const propTypes = { | ||
/** The reportAction's source */ | ||
source: reportActionSourcePropType.isRequired, | ||
|
||
/** The message fragment needing to be displayed */ | ||
fragment: reportActionFragmentPropTypes.isRequired, | ||
|
||
/** Should this message fragment be styled as deleted? */ | ||
styleAsDeleted: PropTypes.bool.isRequired, | ||
|
||
/** Text of an IOU report action */ | ||
iouMessage: PropTypes.string, | ||
|
||
/** Should the comment have the appearance of being grouped with the previous comment? */ | ||
displayAsGroup: PropTypes.bool.isRequired, | ||
|
||
/** Additional styles to add after local styles. */ | ||
style: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.object), PropTypes.object]).isRequired, | ||
|
||
...windowDimensionsPropTypes, | ||
|
||
/** localization props */ | ||
...withLocalizePropTypes, | ||
}; | ||
|
||
const defaultProps = { | ||
iouMessage: undefined, | ||
}; | ||
|
||
function TextCommentFragment(props) { | ||
const {fragment, styleAsDeleted} = props; | ||
const {html, text} = fragment; | ||
|
||
// If the only difference between fragment.text and fragment.html is <br /> tags | ||
// we render it as text, not as html. | ||
// This is done to render emojis with line breaks between them as text. | ||
const differByLineBreaksOnly = Str.replaceAll(html, '<br />', '\n') === text; | ||
|
||
// Only render HTML if we have html in the fragment | ||
if (!differByLineBreaksOnly) { | ||
const editedTag = fragment.isEdited ? `<edited ${styleAsDeleted ? 'deleted' : ''}></edited>` : ''; | ||
const htmlContent = styleAsDeleted ? `<del>${html}</del>` : html; | ||
|
||
const htmlWithTag = editedTag ? `${htmlContent}${editedTag}` : htmlContent; | ||
|
||
return ( | ||
<RenderCommentHTML | ||
source={props.source} | ||
html={htmlWithTag} | ||
/> | ||
); | ||
} | ||
|
||
const containsOnlyEmojis = EmojiUtils.containsOnlyEmojis(text); | ||
|
||
return ( | ||
<Text style={[containsOnlyEmojis ? styles.onlyEmojisText : undefined, styles.ltr, ...props.style]}> | ||
<ZeroWidthView | ||
text={text} | ||
displayAsGroup={props.displayAsGroup} | ||
/> | ||
<Text | ||
style={[ | ||
containsOnlyEmojis ? styles.onlyEmojisText : undefined, | ||
styles.ltr, | ||
...props.style, | ||
styleAsDeleted ? styles.offlineFeedback.deleted : undefined, | ||
!DeviceCapabilities.canUseTouchScreen() || !props.isSmallScreenWidth ? styles.userSelectText : styles.userSelectNone, | ||
]} | ||
> | ||
{convertToLTR(props.iouMessage || text)} | ||
</Text> | ||
{Boolean(fragment.isEdited) && ( | ||
<> | ||
<Text | ||
style={[containsOnlyEmojis ? styles.onlyEmojisTextLineHeight : undefined, styles.userSelectNone]} | ||
dataSet={{[CONST.SELECTION_SCRAPER_HIDDEN_ELEMENT]: true}} | ||
> | ||
{' '} | ||
</Text> | ||
<Text | ||
fontSize={variables.fontSizeSmall} | ||
color={themeColors.textSupporting} | ||
style={[editedLabelStyles, styleAsDeleted ? styles.offlineFeedback.deleted : undefined, ...props.style]} | ||
> | ||
{props.translate('reportActionCompose.edited')} | ||
</Text> | ||
</> | ||
)} | ||
</Text> | ||
); | ||
} | ||
|
||
TextCommentFragment.propTypes = propTypes; | ||
TextCommentFragment.defaultProps = defaultProps; | ||
TextCommentFragment.displayName = 'TextCommentFragment'; | ||
|
||
export default compose(withWindowDimensions, withLocalize)(memo(TextCommentFragment)); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
import PropTypes from 'prop-types'; | ||
|
||
export default PropTypes.oneOf(['Chronos', 'email', 'ios', 'android', 'web', 'email', '']); |