-
Notifications
You must be signed in to change notification settings - Fork 3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[TS migration] Migrate 'AnchorForCommentsOnly' component to TypeScript #32670
Changes from 9 commits
fa0e582
1112a8b
d70f96b
de21d8d
42f9992
3a3a37e
e5baca5
9dafe7a
92e5ab8
b66fe6e
2ba2598
c558403
7bf1386
875cf8a
27cbc79
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||
---|---|---|---|---|
@@ -1,39 +1,26 @@ | ||||
import Str from 'expensify-common/lib/str'; | ||||
import lodashGet from 'lodash/get'; | ||||
import PropTypes from 'prop-types'; | ||||
import React, {useEffect} from 'react'; | ||||
import {StyleSheet} from 'react-native'; | ||||
import _ from 'underscore'; | ||||
import React, {useEffect, useRef} from 'react'; | ||||
import {Text as RNText, StyleSheet} from 'react-native'; | ||||
import PressableWithSecondaryInteraction from '@components/PressableWithSecondaryInteraction'; | ||||
import Text from '@components/Text'; | ||||
import Tooltip from '@components/Tooltip'; | ||||
import useWindowDimensions from '@hooks/useWindowDimensions'; | ||||
import * as DeviceCapabilities from '@libs/DeviceCapabilities'; | ||||
import * as ContextMenuActions from '@pages/home/report/ContextMenu/ContextMenuActions'; | ||||
import * as ReportActionContextMenu from '@pages/home/report/ContextMenu/ReportActionContextMenu'; | ||||
import useStyleUtils from '@styles/useStyleUtils'; | ||||
import useThemeStyles from '@styles/useThemeStyles'; | ||||
import CONST from '@src/CONST'; | ||||
import {propTypes as anchorForCommentsOnlyPropTypes} from './anchorForCommentsOnlyPropTypes'; | ||||
|
||||
const propTypes = { | ||||
/** Press in handler for the link */ | ||||
// eslint-disable-next-line react/require-default-props | ||||
onPressIn: PropTypes.func, | ||||
|
||||
/** Press out handler for the link */ | ||||
// eslint-disable-next-line react/require-default-props | ||||
onPressOut: PropTypes.func, | ||||
|
||||
...anchorForCommentsOnlyPropTypes, | ||||
}; | ||||
import type {BaseAnchorForCommentsOnlyProps, LinkProps} from './types'; | ||||
|
||||
/* | ||||
* This is a default anchor component for regular links. | ||||
*/ | ||||
function BaseAnchorForCommentsOnly({onPressIn, onPressOut, href = '', rel = '', target = '', children = null, style = {}, onPress, ...rest}) { | ||||
function BaseAnchorForCommentsOnly({onPressIn, onPressOut, href = '', rel = '', target = '', children = null, style, onPress, ...rest}: BaseAnchorForCommentsOnlyProps) { | ||||
const styles = useThemeStyles(); | ||||
const StyleUtils = useStyleUtils(); | ||||
const linkRef = useRef<RNText>(null); | ||||
const flattenStyle = StyleSheet.flatten(style); | ||||
|
||||
useEffect( | ||||
() => () => { | ||||
ReportActionContextMenu.hideContextMenu(); | ||||
|
@@ -43,10 +30,8 @@ function BaseAnchorForCommentsOnly({onPressIn, onPressOut, href = '', rel = '', | |||
|
||||
const {isSmallScreenWidth} = useWindowDimensions(); | ||||
|
||||
let linkRef; | ||||
|
||||
const linkProps = {}; | ||||
if (_.isFunction(onPress)) { | ||||
const linkProps: LinkProps = {}; | ||||
if (onPress) { | ||||
linkProps.onPress = onPress; | ||||
} else { | ||||
linkProps.href = href; | ||||
|
@@ -58,21 +43,16 @@ function BaseAnchorForCommentsOnly({onPressIn, onPressOut, href = '', rel = '', | |||
<PressableWithSecondaryInteraction | ||||
inline | ||||
suppressHighlighting | ||||
style={[styles.cursorDefault, StyleUtils.getFontSizeStyle(style.fontSize)]} | ||||
style={[styles.cursorDefault, !!flattenStyle.fontSize && StyleUtils.getFontSizeStyle(flattenStyle.fontSize)]} | ||||
onSecondaryInteraction={(event) => { | ||||
ReportActionContextMenu.showContextMenu( | ||||
isEmail ? ContextMenuActions.CONTEXT_MENU_TYPES.EMAIL : ContextMenuActions.CONTEXT_MENU_TYPES.LINK, | ||||
event, | ||||
href, | ||||
lodashGet(linkRef, 'current'), | ||||
); | ||||
ReportActionContextMenu.showContextMenu(isEmail ? CONST.CONTEXT_MENU_TYPES.EMAIL : CONST.CONTEXT_MENU_TYPES.LINK, event, href, linkRef.current); | ||||
}} | ||||
onPress={(event) => { | ||||
if (!linkProps.onPress) { | ||||
return; | ||||
} | ||||
|
||||
event.preventDefault(); | ||||
event?.preventDefault(); | ||||
linkProps.onPress(); | ||||
}} | ||||
onPressIn={onPressIn} | ||||
|
@@ -82,14 +62,14 @@ function BaseAnchorForCommentsOnly({onPressIn, onPressOut, href = '', rel = '', | |||
> | ||||
<Tooltip text={href}> | ||||
<Text | ||||
ref={(el) => (linkRef = el)} | ||||
ref={linkRef} | ||||
style={StyleSheet.flatten([style, defaultTextStyle])} | ||||
role={CONST.ACCESSIBILITY_ROLE.LINK} | ||||
hrefAttrs={{ | ||||
rel, | ||||
target: isEmail || !linkProps.href ? '_self' : target, | ||||
}} | ||||
href={linkProps.href || href} | ||||
href={href} | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why you got rid of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Because it looks like
|
||||
suppressHighlighting | ||||
// Add testID so it gets selected as an anchor tag by SelectionScraper | ||||
testID="a" | ||||
|
@@ -103,7 +83,6 @@ function BaseAnchorForCommentsOnly({onPressIn, onPressOut, href = '', rel = '', | |||
); | ||||
} | ||||
|
||||
BaseAnchorForCommentsOnly.propTypes = propTypes; | ||||
BaseAnchorForCommentsOnly.displayName = 'BaseAnchorForCommentsOnly'; | ||||
|
||||
export default BaseAnchorForCommentsOnly; |
This file was deleted.
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import React from 'react'; | ||
import {Linking} from 'react-native'; | ||
import BaseAnchorForCommentsOnly from './BaseAnchorForCommentsOnly'; | ||
import type {AnchorForCommentsOnlyProps} from './types'; | ||
|
||
function AnchorForCommentsOnly({onPress, href = '', ...props}: AnchorForCommentsOnlyProps) { | ||
const onLinkPress = () => { | ||
if (onPress) { | ||
onPress(); | ||
} else { | ||
Linking.openURL(href); | ||
} | ||
}; | ||
|
||
return ( | ||
<BaseAnchorForCommentsOnly | ||
// eslint-disable-next-line react/jsx-props-no-spreading | ||
{...props} | ||
href={href} | ||
onPress={onLinkPress} | ||
/> | ||
); | ||
} | ||
|
||
AnchorForCommentsOnly.displayName = 'AnchorForCommentsOnly'; | ||
|
||
export default AnchorForCommentsOnly; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import {StyleProp, TextStyle} from 'react-native'; | ||
import ChildrenProps from '@src/types/utils/ChildrenProps'; | ||
|
||
type AnchorForCommentsOnlyProps = ChildrenProps & { | ||
/** The URL to open */ | ||
href?: 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?: 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?: string; | ||
|
||
/** Any additional styles to apply */ | ||
style: StyleProp<TextStyle>; | ||
|
||
/** Press handler for the link, when not passed, default href is used to create a link like behaviour */ | ||
onPress?: () => void; | ||
}; | ||
|
||
type BaseAnchorForCommentsOnlyProps = AnchorForCommentsOnlyProps & { | ||
/** Press in handler for the link */ | ||
onPressIn?: () => void; | ||
|
||
/** Press out handler for the link */ | ||
onPressOut?: () => void; | ||
}; | ||
|
||
type LinkProps = { | ||
/** Press handler for the link, when not passed, default href is used to create a link like behaviour */ | ||
onPress?: () => void; | ||
|
||
/** The URL to open */ | ||
href?: string; | ||
}; | ||
|
||
export type {AnchorForCommentsOnlyProps, BaseAnchorForCommentsOnlyProps, LinkProps}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we add
'current' in linkRef
check, to avoid possible crash?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@getusha hm, is there a case where
linkRef
doesn't havecurrent
field? I think ref object should have current valueThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like we don't need it as the component is functional component.