diff --git a/src/components/AttachmentModal.js b/src/components/AttachmentModal.js index 6a318b2124bb..1fc8d10c5022 100755 --- a/src/components/AttachmentModal.js +++ b/src/components/AttachmentModal.js @@ -16,6 +16,7 @@ import HeaderWithCloseButton from './HeaderWithCloseButton'; import fileDownload from '../libs/fileDownload'; import withLocalize, {withLocalizePropTypes} from './withLocalize'; import ConfirmModal from './ConfirmModal'; +import TextWithEllipsis from './TextWithEllipsis'; /** * Modal render prop component that exposes modal launching triggers that can be used @@ -89,6 +90,18 @@ class AttachmentModal extends PureComponent { return modalType; } + /** + * Returns the filename split into fileName and fileExtension + * @returns {Object} + */ + splitExtensionFromFileName() { + const fullFileName = this.props.originalFileName ? this.props.originalFileName.trim() : lodashGet(this.state, 'file.name', '').trim(); + const splittedFileName = fullFileName.split('.'); + const fileExtension = splittedFileName.pop(); + const fileName = splittedFileName.join('.'); + return {fileName, fileExtension}; + } + /** * Execute the onConfirm callback and close the modal. */ @@ -129,6 +142,8 @@ class AttachmentModal extends PureComponent { const attachmentViewStyles = this.props.isSmallScreenWidth ? [styles.imageModalImageCenterContainer] : [styles.imageModalImageCenterContainer, styles.p5]; + + const {fileName, fileExtension} = this.splitExtensionFromFileName(); return ( <> fileDownload(sourceURL)} onCloseButtonPress={() => this.setState({isModalOpen: false})} - subtitle={this.props.originalFileName ? this.props.originalFileName : lodashGet(this.state, 'file.name', '')} + subtitle={( + + )} /> {this.state.sourceURL && ( diff --git a/src/components/Header.js b/src/components/Header.js index c692b028fab3..060eb7c82a02 100644 --- a/src/components/Header.js +++ b/src/components/Header.js @@ -1,6 +1,7 @@ import React from 'react'; import {View} from 'react-native'; import PropTypes from 'prop-types'; +import _ from 'underscore'; import styles from '../styles/styles'; import Text from './Text'; import EnvironmentBadge from './EnvironmentBadge'; @@ -10,7 +11,7 @@ const propTypes = { title: PropTypes.string.isRequired, /** Subtitle of the header */ - subtitle: PropTypes.string, + subtitle: PropTypes.oneOfType([PropTypes.string, PropTypes.element]), /** Should we show the environment badge (dev/stg)? */ shouldShowEnvironmentBadge: PropTypes.bool, @@ -22,12 +23,14 @@ const defaultProps = { }; const Header = props => ( - + {props.title} {/* If there's no subtitle then display a fragment to avoid an empty space which moves the main title */} - {props.subtitle ? {props.subtitle} : <> } + {_.isString(props.subtitle) + ? {props.subtitle} + : props.subtitle} {props.shouldShowEnvironmentBadge && ( diff --git a/src/components/HeaderWithCloseButton.js b/src/components/HeaderWithCloseButton.js index d199f50d319c..4680d1974083 100755 --- a/src/components/HeaderWithCloseButton.js +++ b/src/components/HeaderWithCloseButton.js @@ -18,7 +18,7 @@ const propTypes = { title: PropTypes.string, /** Subtitle of the header */ - subtitle: PropTypes.string, + subtitle: PropTypes.oneOfType([PropTypes.string, PropTypes.element]), /** Method to trigger when pressing download button of the header */ onDownloadButtonPress: PropTypes.func, diff --git a/src/components/TextWithEllipsis/index.js b/src/components/TextWithEllipsis/index.js new file mode 100644 index 000000000000..b0e4ee521ff3 --- /dev/null +++ b/src/components/TextWithEllipsis/index.js @@ -0,0 +1,51 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import {View} from 'react-native'; +import Text from '../Text'; +import styles from '../../styles/styles'; +import stylePropTypes from '../../styles/stylePropTypes'; +import * as StyleUtils from '../../styles/StyleUtils'; + +const propTypes = { + /** Leading text before the ellipsis */ + leadingText: PropTypes.string.isRequired, + + /** Text after the ellipsis */ + trailingText: PropTypes.string.isRequired, + + /** Styles for leading and trailing text */ + textStyle: stylePropTypes, + + /** Styles for leading text View */ + leadingTextParentStyle: stylePropTypes, + + /** Styles for parent View */ + wrapperStyle: stylePropTypes, +}; + +const defaultProps = { + textStyle: {}, + leadingTextParentStyle: {}, + wrapperStyle: {}, +}; + +const TextWithEllipsis = props => ( + + + + {props.leadingText} + + + + + {props.trailingText} + + + +); + +TextWithEllipsis.propTypes = propTypes; +TextWithEllipsis.defaultProps = defaultProps; +TextWithEllipsis.displayName = 'TextWithEllipsis'; + +export default TextWithEllipsis; diff --git a/src/pages/home/report/ReportTypingIndicator.js b/src/pages/home/report/ReportTypingIndicator.js index 371b069994f5..aea493cadeb3 100755 --- a/src/pages/home/report/ReportTypingIndicator.js +++ b/src/pages/home/report/ReportTypingIndicator.js @@ -9,6 +9,7 @@ import styles from '../../../styles/styles'; import * as PersonalDetails from '../../../libs/actions/PersonalDetails'; import withLocalize, {withLocalizePropTypes} from '../../../components/withLocalize'; import Text from '../../../components/Text'; +import TextWithEllipsis from '../../../components/TextWithEllipsis'; const propTypes = { /** Key-value pairs of user logins and whether or not they are typing. Keys are logins. */ @@ -52,21 +53,13 @@ class ReportTypingIndicator extends React.Component { return ; case 1: return ( - - - - {PersonalDetails.getDisplayName(this.state.usersTyping[0])} - - - - - {` ${this.props.translate('reportTypingIndicator.isTyping')}`} - - - + ); default: return ( diff --git a/src/styles/StyleUtils.js b/src/styles/StyleUtils.js index b15366c1f808..10e1b56fb412 100644 --- a/src/styles/StyleUtils.js +++ b/src/styles/StyleUtils.js @@ -375,6 +375,15 @@ function getMiniReportActionContextMenuWrapperStyle(isReportActionItemGrouped) { }; } +/** + * Parse styleParam and return Styles array + * @param {Object|Object[]} styleParam + * @returns {Object[]} + */ +function parseStyleAsArray(styleParam) { + return _.isArray(styleParam) ? styleParam : [styleParam]; +} + export { getSafeAreaPadding, getSafeAreaMargins, @@ -397,4 +406,5 @@ export { getLoginPagePromoStyle, getReportActionItemStyle, getMiniReportActionContextMenuWrapperStyle, + parseStyleAsArray, };