Skip to content

Commit

Permalink
Merge pull request #33261 from Expensify/revert-32731-ts/UserDetailsT…
Browse files Browse the repository at this point in the history
…ooltip

Revert "[TS migration] Migrate 'UserDetailsTooltip' component to TypeScript"
  • Loading branch information
robertjchen authored Dec 19, 2023
2 parents 19ca744 + 52664f1 commit 4a9914f
Show file tree
Hide file tree
Showing 14 changed files with 145 additions and 128 deletions.
4 changes: 2 additions & 2 deletions src/components/DisplayNames/DisplayNamesTooltipItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ type DisplayNamesTooltipItemProps = {
index?: number;

/** The function to get a distance to shift the tooltip horizontally */
getTooltipShiftX?: (index: number) => number;
getTooltipShiftX?: (index: number) => number | undefined;

/** The Account ID for the tooltip */
accountID?: number;
Expand All @@ -32,7 +32,7 @@ type DisplayNamesTooltipItemProps = {

function DisplayNamesTooltipItem({
index = 0,
getTooltipShiftX = () => 0,
getTooltipShiftX = () => undefined,
accountID = 0,
avatar = '',
login = '',
Expand Down
6 changes: 3 additions & 3 deletions src/components/DisplayNames/DisplayNamesWithTooltip.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,13 @@ function DisplayNamesWithToolTip({shouldUseFullTitle, fullTitle, displayNamesWit
* 2. Now we get the tooltip original position.
* 3. If inline node's right edge is overflowing the container's right edge, we set the tooltip to the center
* of the distance between the left edge of the inline node and right edge of the container.
* @param index Used to get the Ref to the node at the current index
* @returns Distance to shift the tooltip horizontally
* @param {Number} index Used to get the Ref to the node at the current index
* @returns {Number} Distance to shift the tooltip horizontally
*/
const getTooltipShiftX = useCallback((index: number) => {
// Only shift the tooltip in case the containerLayout or Refs to the text node are available
if (!containerRef.current || !childRefs.current[index]) {
return 0;
return;
}
const {width: containerWidth, left: containerLeft} = containerRef.current.getBoundingClientRect();

Expand Down
2 changes: 1 addition & 1 deletion src/components/Hoverable/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ function Hoverable(
// Expose inner ref to parent through outerRef. This enable us to use ref both in parent and child.
useImperativeHandle<HTMLElement | null, HTMLElement | null>(outerRef, () => ref.current, []);

const child = useMemo(() => React.Children.only(mapChildren(children as ReactElement, isHovered)), [children, isHovered]);
const child = useMemo(() => React.Children.only(mapChildren(children, isHovered)), [children, isHovered]);

const enableHoveredOnMouseEnter = useCallback(
(event: MouseEvent) => {
Expand Down
4 changes: 2 additions & 2 deletions src/components/Hoverable/types.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import {ReactNode} from 'react';
import {ReactElement} from 'react';

type HoverableProps = {
/** Children to wrap with Hoverable. */
children: ((isHovered: boolean) => ReactNode) | ReactNode;
children: ((isHovered: boolean) => ReactElement) | ReactElement;

/** Whether to disable the hover action */
disabled?: boolean;
Expand Down
8 changes: 4 additions & 4 deletions src/components/MultipleAvatars.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ function MultipleAvatars({
if (icons.length === 1 && !shouldStackHorizontally) {
return (
<UserDetailsTooltip
accountID={Number(icons[0].id)}
accountID={icons[0].id}
icon={icons[0]}
fallbackUserDetails={{
displayName: icons[0].name,
Expand Down Expand Up @@ -184,7 +184,7 @@ function MultipleAvatars({
{[...avatars].splice(0, maxAvatarsInRow).map((icon, index) => (
<UserDetailsTooltip
key={`stackedAvatars-${icon.id}`}
accountID={Number(icon.id)}
accountID={icon.id}
icon={icon}
fallbackUserDetails={{
displayName: icon.name,
Expand Down Expand Up @@ -257,7 +257,7 @@ function MultipleAvatars({
<View style={avatarContainerStyles}>
<View style={[singleAvatarStyle, icons[0].type === CONST.ICON_TYPE_WORKSPACE ? StyleUtils.getAvatarBorderRadius(size, icons[0].type) : {}]}>
<UserDetailsTooltip
accountID={Number(icons[0].id)}
accountID={icons[0].id}
icon={icons[0]}
fallbackUserDetails={{
displayName: icons[0].name,
Expand All @@ -279,7 +279,7 @@ function MultipleAvatars({
<View style={[secondAvatarStyles, secondAvatarStyle, icons[1].type === CONST.ICON_TYPE_WORKSPACE ? StyleUtils.getAvatarBorderRadius(size, icons[1].type) : {}]}>
{icons.length === 2 ? (
<UserDetailsTooltip
accountID={Number(icons[1].id)}
accountID={icons[1].id}
icon={icons[1]}
fallbackUserDetails={{
displayName: icons[1].name,
Expand Down
4 changes: 2 additions & 2 deletions src/components/SubscriptAvatar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ function SubscriptAvatar({mainAvatar = {}, secondaryAvatar = {}, size = CONST.AV
<View style={[containerStyle, noMargin ? styles.mr0 : {}]}>
<UserDetailsTooltip
shouldRender={showTooltip}
accountID={Number(mainAvatar.id ?? -1)}
accountID={mainAvatar.id ?? -1}
icon={mainAvatar}
>
<View>
Expand All @@ -75,7 +75,7 @@ function SubscriptAvatar({mainAvatar = {}, secondaryAvatar = {}, size = CONST.AV
</UserDetailsTooltip>
<UserDetailsTooltip
shouldRender={showTooltip}
accountID={Number(secondaryAvatar.id ?? -1)}
accountID={secondaryAvatar.id ?? -1}
icon={secondaryAvatar}
>
<View
Expand Down
8 changes: 5 additions & 3 deletions src/components/Tooltip/types.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import {ReactNode} from 'react';
import ChildrenProps from '@src/types/utils/ChildrenProps';
import {ReactElement, ReactNode} from 'react';

type TooltipProps = ChildrenProps & {
type TooltipProps = {
/** The text to display in the tooltip. If text is ommitted, only children will be rendered. */
text?: string;

/** Maximum number of lines to show in tooltip */
numberOfLines?: number;

/** Children to wrap with Tooltip. */
children: ReactElement;

/** Any additional amount to manually adjust the horizontal position of the tooltip.
A positive value shifts the tooltip to the right, and a negative value shifts it to the left. */
shiftHorizontal?: number | (() => number);
Expand Down
19 changes: 19 additions & 0 deletions src/components/UserDetailsTooltip/BaseUserDetailsTooltip.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import PropTypes from 'prop-types';

const propTypes = {
/** Children to wrap with Tooltip. */
children: PropTypes.node.isRequired,
};

/**
* @param {propTypes} props
* @returns {ReactNodeLike}
*/
function BaseUserDetailsTooltip(props) {
return props.children;
}

BaseUserDetailsTooltip.propTypes = propTypes;
BaseUserDetailsTooltip.displayName = 'BaseUserDetailsTooltip';

export default BaseUserDetailsTooltip;
Original file line number Diff line number Diff line change
@@ -1,55 +1,56 @@
import Str from 'expensify-common/lib/str';
import lodashGet from 'lodash/get';
import React, {useCallback} from 'react';
import {Text, View} from 'react-native';
import _ from 'underscore';
import Avatar from '@components/Avatar';
import {usePersonalDetails} from '@components/OnyxProvider';
import Tooltip from '@components/Tooltip';
import UserDetailsTooltipProps from '@components/UserDetailsTooltip/types';
import useLocalize from '@hooks/useLocalize';
import useThemeStyles from '@hooks/useThemeStyles';
import * as LocalePhoneNumber from '@libs/LocalePhoneNumber';
import * as ReportUtils from '@libs/ReportUtils';
import * as UserUtils from '@libs/UserUtils';
import CONST from '@src/CONST';
import {defaultProps, propTypes} from './userDetailsTooltipPropTypes';

function BaseUserDetailsTooltip({accountID, fallbackUserDetails, icon, delegateAccountID, shiftHorizontal, children}: UserDetailsTooltipProps) {
function BaseUserDetailsTooltip(props) {
const styles = useThemeStyles();
const {translate} = useLocalize();
const personalDetails = usePersonalDetails();

const userDetails = personalDetails?.[accountID] ?? fallbackUserDetails ?? {};
let userDisplayName = ReportUtils.getDisplayNameForParticipant(accountID) ?? (userDetails.displayName ? userDetails.displayName.trim() : '');
let userLogin = userDetails.login?.trim() && userDetails.login !== userDetails.displayName ? Str.removeSMSDomain(userDetails.login) : '';

const userDetails = lodashGet(personalDetails, props.accountID, props.fallbackUserDetails);
let userDisplayName = ReportUtils.getDisplayNameForParticipant(props.accountID) || (userDetails.displayName ? userDetails.displayName.trim() : '');
let userLogin = (userDetails.login || '').trim() && !_.isEqual(userDetails.login, userDetails.displayName) ? Str.removeSMSDomain(userDetails.login) : '';
let userAvatar = userDetails.avatar;
let userAccountID = accountID;
let userAccountID = props.accountID;

// We replace the actor's email, name, and avatar with the Copilot manually for now. This will be improved upon when
// the Copilot feature is implemented.
if (delegateAccountID) {
const delegateUserDetails = personalDetails?.[delegateAccountID] ?? {};
const delegateUserDisplayName = ReportUtils.getDisplayNameForParticipant(delegateAccountID);
if (props.delegateAccountID) {
const delegateUserDetails = lodashGet(personalDetails, props.delegateAccountID, {});
const delegateUserDisplayName = ReportUtils.getDisplayNameForParticipant(props.delegateAccountID);
userDisplayName = `${delegateUserDisplayName} (${translate('reportAction.asCopilot')} ${userDisplayName})`;
userLogin = delegateUserDetails.login ?? '';
userLogin = delegateUserDetails.login;
userAvatar = delegateUserDetails.avatar;
userAccountID = delegateAccountID;
userAccountID = props.delegateAccountID;
}

let title = String(userDisplayName).trim() ? userDisplayName : '';
const subtitle = userLogin.trim() && LocalePhoneNumber.formatPhoneNumber(userLogin) !== userDisplayName ? Str.removeSMSDomain(userLogin) : '';
if (icon && (icon.type === CONST.ICON_TYPE_WORKSPACE || !title)) {
title = icon.name ?? '';
const subtitle = (userLogin || '').trim() && !_.isEqual(LocalePhoneNumber.formatPhoneNumber(userLogin || ''), userDisplayName) ? Str.removeSMSDomain(userLogin) : '';
if (props.icon && (props.icon.type === CONST.ICON_TYPE_WORKSPACE || !title)) {
title = props.icon.name;
}
const renderTooltipContent = useCallback(
() => (
<View style={[styles.alignItemsCenter, styles.ph2, styles.pv2]}>
<View style={styles.emptyAvatar}>
<Avatar
containerStyles={[styles.actionAvatar]}
source={icon ? icon.source : UserUtils.getAvatar(userAvatar, userAccountID)}
type={icon ? icon.type : CONST.ICON_TYPE_AVATAR}
name={icon ? icon.name : userLogin}
fallbackIcon={icon?.fallbackIcon}
source={props.icon ? props.icon.source : UserUtils.getAvatar(userAvatar, userAccountID)}
type={props.icon ? props.icon.type : CONST.ICON_TYPE_AVATAR}
name={props.icon ? props.icon.name : userLogin}
fallbackIcon={lodashGet(props.icon, 'fallbackIcon')}
/>
</View>
<Text style={[styles.mt2, styles.textMicroBold, styles.textReactionSenders, styles.textAlignCenter]}>{title}</Text>
Expand All @@ -70,7 +71,7 @@ function BaseUserDetailsTooltip({accountID, fallbackUserDetails, icon, delegateA
styles.textMicro,
styles.fontColorReactionLabel,
styles.breakWord,
icon,
props.icon,
userAvatar,
userAccountID,
userLogin,
Expand All @@ -79,22 +80,24 @@ function BaseUserDetailsTooltip({accountID, fallbackUserDetails, icon, delegateA
],
);

if (!icon && !userDisplayName && !userLogin) {
return children;
if (!props.icon && !userDisplayName && !userLogin) {
return props.children;
}

return (
<Tooltip
shiftHorizontal={shiftHorizontal}
shiftHorizontal={props.shiftHorizontal}
renderTooltipContent={renderTooltipContent}
renderTooltipContentKey={[userDisplayName, userLogin]}
shouldHandleScroll
>
{children}
{props.children}
</Tooltip>
);
}

BaseUserDetailsTooltip.propTypes = propTypes;
BaseUserDetailsTooltip.defaultProps = defaultProps;
BaseUserDetailsTooltip.displayName = 'BaseUserDetailsTooltip';

export default BaseUserDetailsTooltip;

This file was deleted.

37 changes: 37 additions & 0 deletions src/components/UserDetailsTooltip/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import PropTypes from 'prop-types';
import React from 'react';
import BaseUserDetailsTooltip from './BaseUserDetailsTooltip';
import {defaultProps as userDetailsTooltipDefaultProps, propTypes as userDetailsTooltipPropTypes} from './userDetailsTooltipPropTypes';

const propTypes = {
...userDetailsTooltipPropTypes,

/** Whether the actual UserDetailsTooltip should be rendered. If false, it's just going to return the children */
shouldRender: PropTypes.bool,
};

const defaultProps = {
...userDetailsTooltipDefaultProps,
shouldRender: true,
};

function UserDetailsTooltip({shouldRender = true, children, ...props}) {
if (!shouldRender) {
return children;
}

return (
<BaseUserDetailsTooltip
// eslint-disable-next-line react/jsx-props-no-spreading
{...props}
>
{children}
</BaseUserDetailsTooltip>
);
}

UserDetailsTooltip.displayName = 'UserDetailsTooltip';
UserDetailsTooltip.propTypes = propTypes;
UserDetailsTooltip.defaultProps = defaultProps;

export default UserDetailsTooltip;
22 changes: 0 additions & 22 deletions src/components/UserDetailsTooltip/index.tsx

This file was deleted.

56 changes: 0 additions & 56 deletions src/components/UserDetailsTooltip/types.tsx

This file was deleted.

Loading

0 comments on commit 4a9914f

Please sign in to comment.