From 9bb9bfb7dca14669b11ef42becaf547b58d51db9 Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Fri, 8 Dec 2023 17:28:45 +0100 Subject: [PATCH 1/6] Rename files --- .../index.tsx} | 0 .../index.website.tsx} | 2 +- src/components/UserDetailsTooltip/{index.js => index.tsx} | 2 +- .../{userDetailsTooltipPropTypes.js => types.tsx} | 0 4 files changed, 2 insertions(+), 2 deletions(-) rename src/components/UserDetailsTooltip/{BaseUserDetailsTooltip.js => BaseUserDetailsTooltip/index.tsx} (100%) rename src/components/UserDetailsTooltip/{BaseUserDetailsTooltip.website.js => BaseUserDetailsTooltip/index.website.tsx} (98%) rename src/components/UserDetailsTooltip/{index.js => index.tsx} (93%) rename src/components/UserDetailsTooltip/{userDetailsTooltipPropTypes.js => types.tsx} (100%) diff --git a/src/components/UserDetailsTooltip/BaseUserDetailsTooltip.js b/src/components/UserDetailsTooltip/BaseUserDetailsTooltip/index.tsx similarity index 100% rename from src/components/UserDetailsTooltip/BaseUserDetailsTooltip.js rename to src/components/UserDetailsTooltip/BaseUserDetailsTooltip/index.tsx diff --git a/src/components/UserDetailsTooltip/BaseUserDetailsTooltip.website.js b/src/components/UserDetailsTooltip/BaseUserDetailsTooltip/index.website.tsx similarity index 98% rename from src/components/UserDetailsTooltip/BaseUserDetailsTooltip.website.js rename to src/components/UserDetailsTooltip/BaseUserDetailsTooltip/index.website.tsx index 508bc6f8426c..f665bfc76f35 100644 --- a/src/components/UserDetailsTooltip/BaseUserDetailsTooltip.website.js +++ b/src/components/UserDetailsTooltip/BaseUserDetailsTooltip/index.website.tsx @@ -6,13 +6,13 @@ import _ from 'underscore'; import Avatar from '@components/Avatar'; import {usePersonalDetails} from '@components/OnyxProvider'; import Tooltip from '@components/Tooltip'; +import {defaultProps, propTypes} from '@components/UserDetailsTooltip/types'; import useLocalize from '@hooks/useLocalize'; import * as LocalePhoneNumber from '@libs/LocalePhoneNumber'; import * as ReportUtils from '@libs/ReportUtils'; import * as UserUtils from '@libs/UserUtils'; import useThemeStyles from '@styles/useThemeStyles'; import CONST from '@src/CONST'; -import {defaultProps, propTypes} from './userDetailsTooltipPropTypes'; function BaseUserDetailsTooltip(props) { const styles = useThemeStyles(); diff --git a/src/components/UserDetailsTooltip/index.js b/src/components/UserDetailsTooltip/index.tsx similarity index 93% rename from src/components/UserDetailsTooltip/index.js rename to src/components/UserDetailsTooltip/index.tsx index 6e256ac9ba9e..ed335f09723d 100644 --- a/src/components/UserDetailsTooltip/index.js +++ b/src/components/UserDetailsTooltip/index.tsx @@ -1,7 +1,7 @@ import PropTypes from 'prop-types'; import React from 'react'; import BaseUserDetailsTooltip from './BaseUserDetailsTooltip'; -import {defaultProps as userDetailsTooltipDefaultProps, propTypes as userDetailsTooltipPropTypes} from './userDetailsTooltipPropTypes'; +import {defaultProps as userDetailsTooltipDefaultProps, propTypes as userDetailsTooltipPropTypes} from './types'; const propTypes = { ...userDetailsTooltipPropTypes, diff --git a/src/components/UserDetailsTooltip/userDetailsTooltipPropTypes.js b/src/components/UserDetailsTooltip/types.tsx similarity index 100% rename from src/components/UserDetailsTooltip/userDetailsTooltipPropTypes.js rename to src/components/UserDetailsTooltip/types.tsx From 367abc46ff21c04624e75f4adcec45ef6cb0f0f1 Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Fri, 8 Dec 2023 17:28:55 +0100 Subject: [PATCH 2/6] [TS migration] Migrate 'UserDetailsTooltip' component to TypeScript --- src/components/Hoverable/index.tsx | 2 +- src/components/Hoverable/types.ts | 4 +- src/components/Tooltip/types.ts | 8 +- .../BaseUserDetailsTooltip/index.tsx | 16 +--- .../BaseUserDetailsTooltip/index.website.tsx | 50 ++++++------ src/components/UserDetailsTooltip/index.tsx | 19 +---- src/components/UserDetailsTooltip/types.tsx | 79 +++++++++++-------- 7 files changed, 82 insertions(+), 96 deletions(-) diff --git a/src/components/Hoverable/index.tsx b/src/components/Hoverable/index.tsx index 9c641cfc19be..78ace63bcc35 100644 --- a/src/components/Hoverable/index.tsx +++ b/src/components/Hoverable/index.tsx @@ -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(outerRef, () => ref.current, []); - const child = useMemo(() => React.Children.only(mapChildren(children, isHovered)), [children, isHovered]); + const child = useMemo(() => React.Children.only(mapChildren(children as ReactElement, isHovered)), [children, isHovered]); const enableHoveredOnMouseEnter = useCallback( (event: MouseEvent) => { diff --git a/src/components/Hoverable/types.ts b/src/components/Hoverable/types.ts index 430b865f50c5..b4c53f2df5be 100644 --- a/src/components/Hoverable/types.ts +++ b/src/components/Hoverable/types.ts @@ -1,8 +1,8 @@ -import {ReactElement} from 'react'; +import {ReactNode} from 'react'; type HoverableProps = { /** Children to wrap with Hoverable. */ - children: ((isHovered: boolean) => ReactElement) | ReactElement; + children: ((isHovered: boolean) => ReactNode) | ReactNode; /** Whether to disable the hover action */ disabled?: boolean; diff --git a/src/components/Tooltip/types.ts b/src/components/Tooltip/types.ts index df95c3ea5979..1ca0b5f10747 100644 --- a/src/components/Tooltip/types.ts +++ b/src/components/Tooltip/types.ts @@ -1,15 +1,13 @@ -import {ReactElement, ReactNode} from 'react'; +import {ReactNode} from 'react'; +import ChildrenProps from '@src/types/utils/ChildrenProps'; -type TooltipProps = { +type TooltipProps = ChildrenProps & { /** 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); diff --git a/src/components/UserDetailsTooltip/BaseUserDetailsTooltip/index.tsx b/src/components/UserDetailsTooltip/BaseUserDetailsTooltip/index.tsx index 6c611dae17fd..e490cb13c66b 100644 --- a/src/components/UserDetailsTooltip/BaseUserDetailsTooltip/index.tsx +++ b/src/components/UserDetailsTooltip/BaseUserDetailsTooltip/index.tsx @@ -1,19 +1,9 @@ -import PropTypes from 'prop-types'; +import UserDetailsTooltipProps from '@components/UserDetailsTooltip/types'; -const propTypes = { - /** Children to wrap with Tooltip. */ - children: PropTypes.node.isRequired, -}; - -/** - * @param {propTypes} props - * @returns {ReactNodeLike} - */ -function BaseUserDetailsTooltip(props) { - return props.children; +function BaseUserDetailsTooltip({children}: UserDetailsTooltipProps) { + return children; } -BaseUserDetailsTooltip.propTypes = propTypes; BaseUserDetailsTooltip.displayName = 'BaseUserDetailsTooltip'; export default BaseUserDetailsTooltip; diff --git a/src/components/UserDetailsTooltip/BaseUserDetailsTooltip/index.website.tsx b/src/components/UserDetailsTooltip/BaseUserDetailsTooltip/index.website.tsx index f665bfc76f35..42a692f33288 100644 --- a/src/components/UserDetailsTooltip/BaseUserDetailsTooltip/index.website.tsx +++ b/src/components/UserDetailsTooltip/BaseUserDetailsTooltip/index.website.tsx @@ -1,12 +1,10 @@ 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 {defaultProps, propTypes} from '@components/UserDetailsTooltip/types'; +import UserDetailsTooltipProps from '@components/UserDetailsTooltip/types'; import useLocalize from '@hooks/useLocalize'; import * as LocalePhoneNumber from '@libs/LocalePhoneNumber'; import * as ReportUtils from '@libs/ReportUtils'; @@ -14,32 +12,32 @@ import * as UserUtils from '@libs/UserUtils'; import useThemeStyles from '@styles/useThemeStyles'; import CONST from '@src/CONST'; -function BaseUserDetailsTooltip(props) { +function BaseUserDetailsTooltip({accountID, fallbackUserDetails, icon, delegateAccountID, shiftHorizontal, children}: UserDetailsTooltipProps) { const styles = useThemeStyles(); const {translate} = useLocalize(); const personalDetails = usePersonalDetails(); - const userDetails = lodashGet(personalDetails, props.accountID, props.fallbackUserDetails); - let userDisplayName = ReportUtils.getDisplayNameForParticipant(props.accountID); - let userLogin = (userDetails.login || '').trim() && !_.isEqual(userDetails.login, userDetails.displayName) ? Str.removeSMSDomain(userDetails.login) : ''; + const userDetails = personalDetails[accountID] ?? fallbackUserDetails; + let userDisplayName = ReportUtils.getDisplayNameForParticipant(accountID) ?? ''; + let userLogin = userDetails.login?.trim() && userDetails.login !== userDetails.displayName ? Str.removeSMSDomain(userDetails.login) : ''; let userAvatar = userDetails.avatar; - let userAccountID = props.accountID; + let userAccountID = 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 (props.delegateAccountID) { - const delegateUserDetails = lodashGet(personalDetails, props.delegateAccountID, {}); - const delegateUserDisplayName = ReportUtils.getDisplayNameForParticipant(props.delegateAccountID); + if (delegateAccountID) { + const delegateUserDetails = personalDetails?.[delegateAccountID] ?? {}; + const delegateUserDisplayName = ReportUtils.getDisplayNameForParticipant(delegateAccountID); userDisplayName = `${delegateUserDisplayName} (${translate('reportAction.asCopilot')} ${userDisplayName})`; - userLogin = delegateUserDetails.login; + userLogin = delegateUserDetails.login ?? ''; userAvatar = delegateUserDetails.avatar; - userAccountID = props.delegateAccountID; + userAccountID = delegateAccountID; } let title = String(userDisplayName).trim() ? userDisplayName : ''; - 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 subtitle = userLogin.trim() && LocalePhoneNumber.formatPhoneNumber(userLogin) !== userDisplayName ? Str.removeSMSDomain(userLogin) : ''; + if (icon && (icon.type === CONST.ICON_TYPE_WORKSPACE || !title)) { + title = icon.name ?? ''; } const renderTooltipContent = useCallback( () => ( @@ -47,10 +45,10 @@ function BaseUserDetailsTooltip(props) { {title} @@ -71,7 +69,7 @@ function BaseUserDetailsTooltip(props) { styles.textMicro, styles.fontColorReactionLabel, styles.breakWord, - props.icon, + icon, userAvatar, userAccountID, userLogin, @@ -80,24 +78,22 @@ function BaseUserDetailsTooltip(props) { ], ); - if (!props.icon && !userDisplayName && !userLogin) { - return props.children; + if (!icon && !userDisplayName && !userLogin) { + return children; } return ( - {props.children} + {children} ); } -BaseUserDetailsTooltip.propTypes = propTypes; -BaseUserDetailsTooltip.defaultProps = defaultProps; BaseUserDetailsTooltip.displayName = 'BaseUserDetailsTooltip'; export default BaseUserDetailsTooltip; diff --git a/src/components/UserDetailsTooltip/index.tsx b/src/components/UserDetailsTooltip/index.tsx index ed335f09723d..1ae1688072c9 100644 --- a/src/components/UserDetailsTooltip/index.tsx +++ b/src/components/UserDetailsTooltip/index.tsx @@ -1,21 +1,8 @@ -import PropTypes from 'prop-types'; import React from 'react'; import BaseUserDetailsTooltip from './BaseUserDetailsTooltip'; -import {defaultProps as userDetailsTooltipDefaultProps, propTypes as userDetailsTooltipPropTypes} from './types'; +import UserDetailsTooltipProps from './types'; -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}) { +function UserDetailsTooltip({shouldRender = true, children, ...props}: UserDetailsTooltipProps) { if (!shouldRender) { return children; } @@ -31,7 +18,5 @@ function UserDetailsTooltip({shouldRender = true, children, ...props}) { } UserDetailsTooltip.displayName = 'UserDetailsTooltip'; -UserDetailsTooltip.propTypes = propTypes; -UserDetailsTooltip.defaultProps = defaultProps; export default UserDetailsTooltip; diff --git a/src/components/UserDetailsTooltip/types.tsx b/src/components/UserDetailsTooltip/types.tsx index 538e9ad5348f..d3a662f61954 100644 --- a/src/components/UserDetailsTooltip/types.tsx +++ b/src/components/UserDetailsTooltip/types.tsx @@ -1,43 +1,60 @@ -import PropTypes from 'prop-types'; -import avatarPropTypes from '@components/avatarPropTypes'; -import personalDetailsPropType from '@pages/personalDetailsPropType'; +import {AvatarSource} from '@libs/UserUtils'; +import {AvatarType} from '@src/types/onyx/OnyxCommon'; +import PersonalDetails from '@src/types/onyx/PersonalDetails'; +import ChildrenProps from '@src/types/utils/ChildrenProps'; -const propTypes = { +type FallbackUserDetails = { + /** The name to display in bold */ + displayName?: string; + + /** The login for the tooltip fallback */ + login?: string; + + /** The avatar for the tooltip fallback */ + avatar?: AvatarSource; + + /** Denotes whether it is an avatar or a workspace avatar */ + type?: AvatarType; +}; + +type Icon = { + /** Source for the avatar. Can be a URL or an icon. */ + source?: AvatarSource; + + /** A fallback avatar icon to display when there is an error on loading avatar from remote URL. + * If the avatar is type === workspace, this fallback icon will be ignored and decided based on the name prop. + */ + fallbackIcon?: AvatarSource; + + /** Denotes whether it is an avatar or a workspace avatar */ + type?: AvatarType; + + /** Owner of the avatar. If user, displayName. If workspace, policy name */ + name?: string; +}; + +type UserDetailsTooltipProps = ChildrenProps & { /** User's Account ID */ - accountID: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired, + accountID: number; + /** Fallback User Details object used if no accountID */ - fallbackUserDetails: PropTypes.shape({ - /** Avatar URL */ - avatar: PropTypes.oneOfType([PropTypes.string, PropTypes.func]), - /** Display Name */ - displayName: PropTypes.string, - /** Login */ - login: PropTypes.string, - /** Whether this is a Workspace Avatar or User Avatar */ - type: PropTypes.string, - }), + fallbackUserDetails: FallbackUserDetails; + /** Optionally, pass in the icon instead of calculating it. If defined, will take precedence. */ - icon: avatarPropTypes, - /** Component that displays the tooltip */ - children: PropTypes.node.isRequired, + icon?: Icon; + /** List of personalDetails (keyed by accountID) */ - personalDetailsList: PropTypes.objectOf(personalDetailsPropType), + personalDetailsList: Record; /** The accountID of the copilot who took this action on behalf of the user */ - delegateAccountID: PropTypes.number, + delegateAccountID?: number; /** 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: PropTypes.oneOfType([PropTypes.number, PropTypes.func]), -}; + A positive value shifts the tooltip to the right, and a negative value shifts it to the left. */ + shiftHorizontal?: number | (() => number); -const defaultProps = { - accountID: '', - fallbackUserDetails: {displayName: '', login: '', avatar: '', type: ''}, - personalDetailsList: {}, - delegateAccountID: 0, - icon: undefined, - shiftHorizontal: 0, + /** Whether the actual UserDetailsTooltip should be rendered. If false, it's just going to return the children */ + shouldRender?: boolean; }; -export {propTypes, defaultProps}; +export default UserDetailsTooltipProps; From dc616c4e9d6566260d68a157ed5629705d0a48b2 Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Mon, 11 Dec 2023 12:03:29 +0100 Subject: [PATCH 3/6] Fix typecheck --- src/components/DisplayNames/DisplayNamesTooltipItem.tsx | 4 ++-- src/components/DisplayNames/DisplayNamesWithTooltip.tsx | 6 +++--- src/components/MultipleAvatars.tsx | 8 ++++---- src/components/SubscriptAvatar.tsx | 4 ++-- src/components/UserDetailsTooltip/types.tsx | 6 +----- 5 files changed, 12 insertions(+), 16 deletions(-) diff --git a/src/components/DisplayNames/DisplayNamesTooltipItem.tsx b/src/components/DisplayNames/DisplayNamesTooltipItem.tsx index 82f9c5799b78..a576c919f6cf 100644 --- a/src/components/DisplayNames/DisplayNamesTooltipItem.tsx +++ b/src/components/DisplayNames/DisplayNamesTooltipItem.tsx @@ -9,7 +9,7 @@ type DisplayNamesTooltipItemProps = { index?: number; /** The function to get a distance to shift the tooltip horizontally */ - getTooltipShiftX?: (index: number) => number | undefined; + getTooltipShiftX?: (index: number) => number; /** The Account ID for the tooltip */ accountID?: number; @@ -32,7 +32,7 @@ type DisplayNamesTooltipItemProps = { function DisplayNamesTooltipItem({ index = 0, - getTooltipShiftX = () => undefined, + getTooltipShiftX = () => 0, accountID = 0, avatar = '', login = '', diff --git a/src/components/DisplayNames/DisplayNamesWithTooltip.tsx b/src/components/DisplayNames/DisplayNamesWithTooltip.tsx index 8c8720c7c99f..95a2c3e04824 100644 --- a/src/components/DisplayNames/DisplayNamesWithTooltip.tsx +++ b/src/components/DisplayNames/DisplayNamesWithTooltip.tsx @@ -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 {Number} index Used to get the Ref to the node at the current index - * @returns {Number} Distance to shift the tooltip horizontally + * @param index Used to get the Ref to the node at the current index + * @returns 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; + return 0; } const {width: containerWidth, left: containerLeft} = containerRef.current.getBoundingClientRect(); diff --git a/src/components/MultipleAvatars.tsx b/src/components/MultipleAvatars.tsx index a7b22a663e08..46089b21f64a 100644 --- a/src/components/MultipleAvatars.tsx +++ b/src/components/MultipleAvatars.tsx @@ -142,7 +142,7 @@ function MultipleAvatars({ if (icons.length === 1 && !shouldStackHorizontally) { return ( ( {icons.length === 2 ? ( @@ -75,7 +75,7 @@ function SubscriptAvatar({mainAvatar = {}, secondaryAvatar = {}, size = CONST.AV ; - /** The accountID of the copilot who took this action on behalf of the user */ delegateAccountID?: number; From cc9db1e069715278833a4e6a596bda36a4648169 Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Mon, 11 Dec 2023 18:12:15 +0100 Subject: [PATCH 4/6] Add optional chaining for extra security --- .../UserDetailsTooltip/BaseUserDetailsTooltip/index.website.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/UserDetailsTooltip/BaseUserDetailsTooltip/index.website.tsx b/src/components/UserDetailsTooltip/BaseUserDetailsTooltip/index.website.tsx index 42a692f33288..d585b832252d 100644 --- a/src/components/UserDetailsTooltip/BaseUserDetailsTooltip/index.website.tsx +++ b/src/components/UserDetailsTooltip/BaseUserDetailsTooltip/index.website.tsx @@ -17,7 +17,7 @@ function BaseUserDetailsTooltip({accountID, fallbackUserDetails, icon, delegateA const {translate} = useLocalize(); const personalDetails = usePersonalDetails(); - const userDetails = personalDetails[accountID] ?? fallbackUserDetails; + const userDetails = personalDetails?.[accountID] ?? fallbackUserDetails; let userDisplayName = ReportUtils.getDisplayNameForParticipant(accountID) ?? ''; let userLogin = userDetails.login?.trim() && userDetails.login !== userDetails.displayName ? Str.removeSMSDomain(userDetails.login) : ''; let userAvatar = userDetails.avatar; From cf89cd61cc430376ced0a5a68f37f4a1969d3923 Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Tue, 12 Dec 2023 16:36:22 +0100 Subject: [PATCH 5/6] Fix crash when opening an app --- .../UserDetailsTooltip/BaseUserDetailsTooltip/index.website.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/UserDetailsTooltip/BaseUserDetailsTooltip/index.website.tsx b/src/components/UserDetailsTooltip/BaseUserDetailsTooltip/index.website.tsx index d585b832252d..788b276287e1 100644 --- a/src/components/UserDetailsTooltip/BaseUserDetailsTooltip/index.website.tsx +++ b/src/components/UserDetailsTooltip/BaseUserDetailsTooltip/index.website.tsx @@ -17,7 +17,7 @@ function BaseUserDetailsTooltip({accountID, fallbackUserDetails, icon, delegateA const {translate} = useLocalize(); const personalDetails = usePersonalDetails(); - const userDetails = personalDetails?.[accountID] ?? fallbackUserDetails; + const userDetails = personalDetails?.[accountID] ?? fallbackUserDetails ?? {}; let userDisplayName = ReportUtils.getDisplayNameForParticipant(accountID) ?? ''; let userLogin = userDetails.login?.trim() && userDetails.login !== userDetails.displayName ? Str.removeSMSDomain(userDetails.login) : ''; let userAvatar = userDetails.avatar; From 7ebcf2463401e5fb5b2049ffc14edae6381ddf84 Mon Sep 17 00:00:00 2001 From: Blazej Kustra Date: Thu, 14 Dec 2023 17:37:14 +0100 Subject: [PATCH 6/6] Raname files so that website is a default implementation --- .../BaseUserDetailsTooltip/index.native.tsx | 9 ++ .../BaseUserDetailsTooltip/index.tsx | 95 ++++++++++++++++- .../BaseUserDetailsTooltip/index.website.tsx | 100 ------------------ src/components/UserDetailsTooltip/index.tsx | 2 +- 4 files changed, 103 insertions(+), 103 deletions(-) create mode 100644 src/components/UserDetailsTooltip/BaseUserDetailsTooltip/index.native.tsx delete mode 100644 src/components/UserDetailsTooltip/BaseUserDetailsTooltip/index.website.tsx diff --git a/src/components/UserDetailsTooltip/BaseUserDetailsTooltip/index.native.tsx b/src/components/UserDetailsTooltip/BaseUserDetailsTooltip/index.native.tsx new file mode 100644 index 000000000000..e490cb13c66b --- /dev/null +++ b/src/components/UserDetailsTooltip/BaseUserDetailsTooltip/index.native.tsx @@ -0,0 +1,9 @@ +import UserDetailsTooltipProps from '@components/UserDetailsTooltip/types'; + +function BaseUserDetailsTooltip({children}: UserDetailsTooltipProps) { + return children; +} + +BaseUserDetailsTooltip.displayName = 'BaseUserDetailsTooltip'; + +export default BaseUserDetailsTooltip; diff --git a/src/components/UserDetailsTooltip/BaseUserDetailsTooltip/index.tsx b/src/components/UserDetailsTooltip/BaseUserDetailsTooltip/index.tsx index e490cb13c66b..bebea1418342 100644 --- a/src/components/UserDetailsTooltip/BaseUserDetailsTooltip/index.tsx +++ b/src/components/UserDetailsTooltip/BaseUserDetailsTooltip/index.tsx @@ -1,7 +1,98 @@ +import Str from 'expensify-common/lib/str'; +import React, {useCallback} from 'react'; +import {Text, View} from 'react-native'; +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'; -function BaseUserDetailsTooltip({children}: UserDetailsTooltipProps) { - return children; +function BaseUserDetailsTooltip({accountID, fallbackUserDetails, icon, delegateAccountID, shiftHorizontal, children}: UserDetailsTooltipProps) { + 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) : ''; + + let userAvatar = userDetails.avatar; + let userAccountID = 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); + userDisplayName = `${delegateUserDisplayName} (${translate('reportAction.asCopilot')} ${userDisplayName})`; + userLogin = delegateUserDetails.login ?? ''; + userAvatar = delegateUserDetails.avatar; + userAccountID = 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 renderTooltipContent = useCallback( + () => ( + + + + + {title} + {subtitle} + + ), + + [ + styles.alignItemsCenter, + styles.ph2, + styles.pv2, + styles.emptyAvatar, + styles.actionAvatar, + styles.mt2, + styles.textMicroBold, + styles.textReactionSenders, + styles.textAlignCenter, + styles.textMicro, + styles.fontColorReactionLabel, + styles.breakWord, + icon, + userAvatar, + userAccountID, + userLogin, + title, + subtitle, + ], + ); + + if (!icon && !userDisplayName && !userLogin) { + return children; + } + + return ( + + {children} + + ); } BaseUserDetailsTooltip.displayName = 'BaseUserDetailsTooltip'; diff --git a/src/components/UserDetailsTooltip/BaseUserDetailsTooltip/index.website.tsx b/src/components/UserDetailsTooltip/BaseUserDetailsTooltip/index.website.tsx deleted file mode 100644 index bebea1418342..000000000000 --- a/src/components/UserDetailsTooltip/BaseUserDetailsTooltip/index.website.tsx +++ /dev/null @@ -1,100 +0,0 @@ -import Str from 'expensify-common/lib/str'; -import React, {useCallback} from 'react'; -import {Text, View} from 'react-native'; -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'; - -function BaseUserDetailsTooltip({accountID, fallbackUserDetails, icon, delegateAccountID, shiftHorizontal, children}: UserDetailsTooltipProps) { - 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) : ''; - - let userAvatar = userDetails.avatar; - let userAccountID = 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); - userDisplayName = `${delegateUserDisplayName} (${translate('reportAction.asCopilot')} ${userDisplayName})`; - userLogin = delegateUserDetails.login ?? ''; - userAvatar = delegateUserDetails.avatar; - userAccountID = 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 renderTooltipContent = useCallback( - () => ( - - - - - {title} - {subtitle} - - ), - - [ - styles.alignItemsCenter, - styles.ph2, - styles.pv2, - styles.emptyAvatar, - styles.actionAvatar, - styles.mt2, - styles.textMicroBold, - styles.textReactionSenders, - styles.textAlignCenter, - styles.textMicro, - styles.fontColorReactionLabel, - styles.breakWord, - icon, - userAvatar, - userAccountID, - userLogin, - title, - subtitle, - ], - ); - - if (!icon && !userDisplayName && !userLogin) { - return children; - } - - return ( - - {children} - - ); -} - -BaseUserDetailsTooltip.displayName = 'BaseUserDetailsTooltip'; - -export default BaseUserDetailsTooltip; diff --git a/src/components/UserDetailsTooltip/index.tsx b/src/components/UserDetailsTooltip/index.tsx index 1ae1688072c9..71e3a9f433cf 100644 --- a/src/components/UserDetailsTooltip/index.tsx +++ b/src/components/UserDetailsTooltip/index.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import BaseUserDetailsTooltip from './BaseUserDetailsTooltip'; +import BaseUserDetailsTooltip from './BaseUserDetailsTooltip/index.native'; import UserDetailsTooltipProps from './types'; function UserDetailsTooltip({shouldRender = true, children, ...props}: UserDetailsTooltipProps) {