diff --git a/src/components/AnchorForCommentsOnly.js b/src/components/AnchorForCommentsOnly.js deleted file mode 100644 index c93ecb416b64..000000000000 --- a/src/components/AnchorForCommentsOnly.js +++ /dev/null @@ -1,107 +0,0 @@ -import _ from 'underscore'; -import React from 'react'; -import {StyleSheet} from 'react-native'; -import lodashGet from 'lodash/get'; -import Str from 'expensify-common/lib/str'; -import PropTypes from 'prop-types'; -import Text from './Text'; -import PressableWithSecondaryInteraction from './PressableWithSecondaryInteraction'; -import * as ReportActionContextMenu from '../pages/home/report/ContextMenu/ReportActionContextMenu'; -import * as ContextMenuActions from '../pages/home/report/ContextMenu/ContextMenuActions'; -import Tooltip from './Tooltip'; -import canUseTouchScreen from '../libs/canUseTouchscreen'; -import styles from '../styles/styles'; -import withWindowDimensions, {windowDimensionsPropTypes} from './withWindowDimensions'; - -const propTypes = { - /** The URL to open */ - href: PropTypes.string, - - /** What headers to send to the linked page (usually noopener and noreferrer) - This is unused in native, but is here for parity with web */ - rel: PropTypes.string, - - /** Used to determine where to open a link ("_blank" is passed for a new tab) - This is unused in native, but is here for parity with web */ - target: PropTypes.string, - - /** Any children to display */ - children: PropTypes.node, - - /** Anchor text of URLs or emails. */ - displayName: PropTypes.string, - - /** Any additional styles to apply */ - // eslint-disable-next-line react/forbid-prop-types - style: PropTypes.any, - - /** Press handler for the link, when not passed, default href is used to create a link like behaviour */ - onPress: PropTypes.func, - - ...windowDimensionsPropTypes, -}; - -const defaultProps = { - href: '', - rel: '', - target: '', - children: null, - style: {}, - displayName: '', - onPress: undefined, -}; - -/* - * This is a default anchor component for regular links. - */ -const BaseAnchorForCommentsOnly = (props) => { - let linkRef; - const rest = _.omit(props, _.keys(propTypes)); - const linkProps = {}; - if (_.isFunction(props.onPress)) { - linkProps.onPress = props.onPress; - } else { - linkProps.href = props.href; - } - const defaultTextStyle = canUseTouchScreen() || props.isSmallScreenWidth ? {} : styles.userSelectText; - - return ( - { - ReportActionContextMenu.showContextMenu( - Str.isValidEmail(props.displayName) ? ContextMenuActions.CONTEXT_MENU_TYPES.EMAIL : ContextMenuActions.CONTEXT_MENU_TYPES.LINK, - event, - props.href, - lodashGet(linkRef, 'current'), - ); - } - } - > - - linkRef = el} - style={StyleSheet.flatten([props.style, defaultTextStyle])} - accessibilityRole="link" - hrefAttrs={{ - rel: props.rel, - target: props.target, - }} - // eslint-disable-next-line react/jsx-props-no-spreading - {...linkProps} - // eslint-disable-next-line react/jsx-props-no-spreading - {...rest} - > - {props.children} - - - - ); -}; - -BaseAnchorForCommentsOnly.propTypes = propTypes; -BaseAnchorForCommentsOnly.defaultProps = defaultProps; -BaseAnchorForCommentsOnly.displayName = 'BaseAnchorForCommentsOnly'; - -export default withWindowDimensions(BaseAnchorForCommentsOnly); diff --git a/src/components/AnchorForCommentsOnly/BaseAnchorForCommentsOnly.js b/src/components/AnchorForCommentsOnly/BaseAnchorForCommentsOnly.js new file mode 100644 index 000000000000..e65b423fa517 --- /dev/null +++ b/src/components/AnchorForCommentsOnly/BaseAnchorForCommentsOnly.js @@ -0,0 +1,69 @@ +import _ from 'underscore'; +import React from 'react'; +import {StyleSheet} from 'react-native'; +import lodashGet from 'lodash/get'; +import Str from 'expensify-common/lib/str'; +import Text from '../Text'; +import PressableWithSecondaryInteraction from '../PressableWithSecondaryInteraction'; +import * as ReportActionContextMenu from '../../pages/home/report/ContextMenu/ReportActionContextMenu'; +import * as ContextMenuActions from '../../pages/home/report/ContextMenu/ContextMenuActions'; +import Tooltip from '../Tooltip'; +import canUseTouchScreen from '../../libs/canUseTouchscreen'; +import styles from '../../styles/styles'; +import withWindowDimensions from '../withWindowDimensions'; +import {propTypes, defaultProps} from './anchorForCommentsOnlyPropTypes'; + +/* + * This is a default anchor component for regular links. + */ +const BaseAnchorForCommentsOnly = (props) => { + let linkRef; + const rest = _.omit(props, _.keys(propTypes)); + const linkProps = {}; + if (_.isFunction(props.onPress)) { + linkProps.onPress = props.onPress; + } else { + linkProps.href = props.href; + } + const defaultTextStyle = canUseTouchScreen() || props.isSmallScreenWidth ? {} : styles.userSelectText; + + return ( + { + ReportActionContextMenu.showContextMenu( + Str.isValidEmail(props.displayName) ? ContextMenuActions.CONTEXT_MENU_TYPES.EMAIL : ContextMenuActions.CONTEXT_MENU_TYPES.LINK, + event, + props.href, + lodashGet(linkRef, 'current'), + ); + } + } + > + + linkRef = el} + style={StyleSheet.flatten([props.style, defaultTextStyle])} + accessibilityRole="link" + hrefAttrs={{ + rel: props.rel, + target: props.target, + }} + // eslint-disable-next-line react/jsx-props-no-spreading + {...linkProps} + // eslint-disable-next-line react/jsx-props-no-spreading + {...rest} + > + {props.children} + + + + ); +}; + +BaseAnchorForCommentsOnly.propTypes = propTypes; +BaseAnchorForCommentsOnly.defaultProps = defaultProps; +BaseAnchorForCommentsOnly.displayName = 'BaseAnchorForCommentsOnly'; + +export default withWindowDimensions(BaseAnchorForCommentsOnly); diff --git a/src/components/AnchorForCommentsOnly/anchorForCommentsOnlyPropTypes.js b/src/components/AnchorForCommentsOnly/anchorForCommentsOnlyPropTypes.js new file mode 100644 index 000000000000..7661efaf0af3 --- /dev/null +++ b/src/components/AnchorForCommentsOnly/anchorForCommentsOnlyPropTypes.js @@ -0,0 +1,42 @@ +import PropTypes from 'prop-types'; +import stylePropTypes from '../../styles/stylePropTypes'; +import {windowDimensionsPropTypes} from '../withWindowDimensions'; + +const propTypes = { + /** The URL to open */ + href: PropTypes.string, + + /** What headers to send to the linked page (usually noopener and noreferrer) + This is unused in native, but is here for parity with web */ + rel: PropTypes.string, + + /** Used to determine where to open a link ("_blank" is passed for a new tab) + This is unused in native, but is here for parity with web */ + target: PropTypes.string, + + /** Any children to display */ + children: PropTypes.node, + + /** Anchor text of URLs or emails. */ + displayName: PropTypes.string, + + /** Any additional styles to apply */ + style: stylePropTypes, + + /** Press handler for the link, when not passed, default href is used to create a link like behaviour */ + onPress: PropTypes.func, + + ...windowDimensionsPropTypes, +}; + +const defaultProps = { + href: '', + rel: '', + target: '', + children: null, + style: {}, + displayName: '', + onPress: undefined, +}; + +export {propTypes, defaultProps}; diff --git a/src/components/AnchorForCommentsOnly/index.js b/src/components/AnchorForCommentsOnly/index.js new file mode 100644 index 000000000000..1526e78007fe --- /dev/null +++ b/src/components/AnchorForCommentsOnly/index.js @@ -0,0 +1,11 @@ +import React from 'react'; +import * as anchorForCommentsOnlyPropTypes from './anchorForCommentsOnlyPropTypes'; +import BaseAnchorForCommentsOnly from './BaseAnchorForCommentsOnly'; + +// eslint-disable-next-line react/jsx-props-no-spreading +const AnchorForCommentsOnly = props => ; +AnchorForCommentsOnly.propTypes = anchorForCommentsOnlyPropTypes.propTypes; +AnchorForCommentsOnly.defaultProps = anchorForCommentsOnlyPropTypes.defaultProps; +AnchorForCommentsOnly.displayName = 'AnchorForCommentsOnly'; + +export default AnchorForCommentsOnly; diff --git a/src/components/AnchorForCommentsOnly/index.native.js b/src/components/AnchorForCommentsOnly/index.native.js new file mode 100644 index 000000000000..e692ea57afbb --- /dev/null +++ b/src/components/AnchorForCommentsOnly/index.native.js @@ -0,0 +1,20 @@ +import React from 'react'; +import {Linking} from 'react-native'; +import _ from 'underscore'; + +import * as anchorForCommentsOnlyPropTypes from './anchorForCommentsOnlyPropTypes'; +import BaseAnchorForCommentsOnly from './BaseAnchorForCommentsOnly'; + +// eslint-disable-next-line react/jsx-props-no-spreading +const AnchorForCommentsOnly = (props) => { + const onPress = () => (_.isFunction(props.onPress) ? props.onPress() : Linking.openURL(props.href)); + + // eslint-disable-next-line react/jsx-props-no-spreading + return ; +}; + +AnchorForCommentsOnly.propTypes = anchorForCommentsOnlyPropTypes.propTypes; +AnchorForCommentsOnly.defaultProps = anchorForCommentsOnlyPropTypes.defaultProps; +AnchorForCommentsOnly.displayName = 'AnchorForCommentsOnly'; + +export default AnchorForCommentsOnly; diff --git a/src/components/HTMLEngineProvider/HTMLRenderers/AnchorRenderer.js b/src/components/HTMLEngineProvider/HTMLRenderers/AnchorRenderer.js index 9d395a8779b9..36adfe30f6b5 100644 --- a/src/components/HTMLEngineProvider/HTMLRenderers/AnchorRenderer.js +++ b/src/components/HTMLEngineProvider/HTMLRenderers/AnchorRenderer.js @@ -85,7 +85,7 @@ const AnchorRenderer = (props) => { displayName={displayName} // Only pass the press handler for internal links, for public links fallback to default link handling - onPress={internalNewExpensifyPath || internalExpensifyPath ? navigateToLink : undefined} + onPress={(internalNewExpensifyPath || internalExpensifyPath) ? navigateToLink : undefined} >