Skip to content
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

Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/CONST.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2895,6 +2895,14 @@ const CONST = {
DEFAULT: 5,
CAROUSEL: 3,
},

/** Context menu types */
CONTEXT_MENU_TYPES: {
LINK: 'LINK',
REPORT_ACTION: 'REPORT_ACTION',
EMAIL: 'EMAIL',
REPORT: 'REPORT',
},
} as const;

export default CONST;
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();
Expand All @@ -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;
Expand All @@ -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);
Copy link
Contributor

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?

Copy link
Contributor Author

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 have current field? I think ref object should have current value

Copy link
Contributor

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.

}}
onPress={(event) => {
if (!linkProps.onPress) {
return;
}

event.preventDefault();
event?.preventDefault();
linkProps.onPress();
}}
onPressIn={onPressIn}
Expand All @@ -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}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why you got rid of linkProps.href ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because it looks likelinkProps.href is or have href value or undefined anyway

suppressHighlighting
// Add testID so it gets selected as an anchor tag by SelectionScraper
testID="a"
Expand All @@ -103,7 +83,6 @@ function BaseAnchorForCommentsOnly({onPressIn, onPressOut, href = '', rel = '',
);
}

BaseAnchorForCommentsOnly.propTypes = propTypes;
BaseAnchorForCommentsOnly.displayName = 'BaseAnchorForCommentsOnly';

export default BaseAnchorForCommentsOnly;

This file was deleted.

24 changes: 0 additions & 24 deletions src/components/AnchorForCommentsOnly/index.native.js

This file was deleted.

27 changes: 27 additions & 0 deletions src/components/AnchorForCommentsOnly/index.native.tsx
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
@@ -1,10 +1,10 @@
import React from 'react';
import ControlSelection from '@libs/ControlSelection';
import * as DeviceCapabilities from '@libs/DeviceCapabilities';
import * as anchorForCommentsOnlyPropTypes from './anchorForCommentsOnlyPropTypes';
import BaseAnchorForCommentsOnly from './BaseAnchorForCommentsOnly';
import type {AnchorForCommentsOnlyProps} from './types';

function AnchorForCommentsOnly(props) {
function AnchorForCommentsOnly(props: AnchorForCommentsOnlyProps) {
return (
<BaseAnchorForCommentsOnly
// eslint-disable-next-line react/jsx-props-no-spreading
Expand All @@ -15,8 +15,6 @@ function AnchorForCommentsOnly(props) {
);
}

AnchorForCommentsOnly.propTypes = anchorForCommentsOnlyPropTypes.propTypes;
AnchorForCommentsOnly.defaultProps = anchorForCommentsOnlyPropTypes.defaultProps;
AnchorForCommentsOnly.displayName = 'AnchorForCommentsOnly';

export default AnchorForCommentsOnly;
39 changes: 39 additions & 0 deletions src/components/AnchorForCommentsOnly/types.ts
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};
3 changes: 1 addition & 2 deletions src/components/LHNOptionsList/OptionRowLHN.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import {getGroupChatName} from '@libs/GroupChatUtils';
import * as OptionsListUtils from '@libs/OptionsListUtils';
import ReportActionComposeFocusManager from '@libs/ReportActionComposeFocusManager';
import * as ReportUtils from '@libs/ReportUtils';
import * as ContextMenuActions from '@pages/home/report/ContextMenu/ContextMenuActions';
import * as ReportActionContextMenu from '@pages/home/report/ContextMenu/ReportActionContextMenu';
import useTheme from '@styles/themes/useTheme';
import useStyleUtils from '@styles/useStyleUtils';
Expand Down Expand Up @@ -130,7 +129,7 @@ function OptionRowLHN(props) {
}
setIsContextMenuActive(true);
ReportActionContextMenu.showContextMenu(
ContextMenuActions.CONTEXT_MENU_TYPES.REPORT,
CONST.CONTEXT_MENU_TYPES.REPORT,
event,
'',
popoverAnchor,
Expand Down
6 changes: 3 additions & 3 deletions src/components/MenuItemList.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import PropTypes from 'prop-types';
import React from 'react';
import _ from 'underscore';
import useSingleExecution from '@hooks/useSingleExecution';
import {CONTEXT_MENU_TYPES} from '@pages/home/report/ContextMenu/ContextMenuActions';
import * as ReportActionContextMenu from '@pages/home/report/ContextMenu/ReportActionContextMenu';
import CONST from '@src/CONST';
import MenuItem from './MenuItem';
import menuItemPropTypes from './menuItemPropTypes';

Expand Down Expand Up @@ -31,9 +31,9 @@ function MenuItemList(props) {
*/
const secondaryInteraction = (link, e) => {
if (typeof link === 'function') {
link().then((url) => ReportActionContextMenu.showContextMenu(CONTEXT_MENU_TYPES.LINK, e, url, popoverAnchor));
link().then((url) => ReportActionContextMenu.showContextMenu(CONST.CONTEXT_MENU_TYPES.LINK, e, url, popoverAnchor));
} else if (!_.isEmpty(link)) {
ReportActionContextMenu.showContextMenu(CONTEXT_MENU_TYPES.LINK, e, link, popoverAnchor);
ReportActionContextMenu.showContextMenu(CONST.CONTEXT_MENU_TYPES.LINK, e, link, popoverAnchor);
}
};

Expand Down
4 changes: 2 additions & 2 deletions src/components/ShowContextMenuContext.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import React from 'react';
import * as DeviceCapabilities from '@libs/DeviceCapabilities';
import * as ReportUtils from '@libs/ReportUtils';
import * as ContextMenuActions from '@pages/home/report/ContextMenu/ContextMenuActions';
import * as ReportActionContextMenu from '@pages/home/report/ContextMenu/ReportActionContextMenu';
import CONST from '@src/CONST';

const ShowContextMenuContext = React.createContext({
anchor: null,
Expand All @@ -28,7 +28,7 @@ function showContextMenuForReport(event, anchor, reportID, action, checkIfContex
return;
}
ReportActionContextMenu.showContextMenu(
ContextMenuActions.CONTEXT_MENU_TYPES.REPORT_ACTION,
CONST.CONTEXT_MENU_TYPES.REPORT_ACTION,
event,
'',
anchor,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import useStyleUtils from '@styles/useStyleUtils';
import * as Session from '@userActions/Session';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import ContextMenuActions, {CONTEXT_MENU_TYPES} from './ContextMenuActions';
import ContextMenuActions from './ContextMenuActions';
import {defaultProps as GenericReportActionContextMenuDefaultProps, propTypes as genericReportActionContextMenuPropTypes} from './genericReportActionContextMenuPropTypes';
import {hideContextMenu} from './ReportActionContextMenu';

Expand All @@ -41,7 +41,7 @@ const propTypes = {
};

const defaultProps = {
type: CONTEXT_MENU_TYPES.REPORT_ACTION,
type: CONST.CONTEXT_MENU_TYPES.REPORT_ACTION,
anchor: null,
contentRef: null,
isChronosReport: false,
Expand Down
Loading