diff --git a/src/components/ParentNavigationSubtitle.tsx b/src/components/ParentNavigationSubtitle.tsx index b62fe4be392f..fede702f9f31 100644 --- a/src/components/ParentNavigationSubtitle.tsx +++ b/src/components/ParentNavigationSubtitle.tsx @@ -1,7 +1,7 @@ import {useRoute} from '@react-navigation/native'; -import React from 'react'; +import React, {useMemo} from 'react'; import type {ColorValue, StyleProp, TextStyle, ViewStyle} from 'react-native'; -import {View} from 'react-native'; +import {StyleSheet, View} from 'react-native'; import useHover from '@hooks/useHover'; import useLocalize from '@hooks/useLocalize'; import useOnyx from '@hooks/useOnyx'; @@ -59,6 +59,9 @@ type ParentNavigationSubtitleProps = { /** The number of lines for the subtitle */ subtitleNumberOfLines?: number; + + /** Whether to show the "from" text prefix */ + shouldShowFrom?: boolean; }; function ParentNavigationSubtitle({ @@ -74,6 +77,7 @@ function ParentNavigationSubtitle({ statusTextColor, statusTextContainerStyles, subtitleNumberOfLines = 1, + shouldShowFrom = true, }: ParentNavigationSubtitleProps) { const currentRoute = useRoute(); const styles = useThemeStyles(); @@ -110,6 +114,15 @@ function ParentNavigationSubtitle({ }; }); + // Extract color from textStyles to apply only to non-link text, preserving link color + const textStylesWithoutColor = useMemo(() => { + if (!textStyles) { + return textStyles; + } + const {color, ...rest} = StyleSheet.flatten(textStyles); + return rest; + }, [textStyles]); + // We should not display the parent navigation subtitle if the user does not have access to the parent chat (the reportName is empty in this case) if (!reportName) { return; @@ -208,7 +221,7 @@ function ParentNavigationSubtitle({ > {!!reportName && ( <> - {`${translate('threads.from')} `} + {shouldShowFrom && {`${translate('threads.from')} `}} {hasAccessToParentReport ? ( diff --git a/src/pages/ReportDetailsPage.tsx b/src/pages/ReportDetailsPage.tsx index 9cbda7d61d0b..2364ee8f5310 100644 --- a/src/pages/ReportDetailsPage.tsx +++ b/src/pages/ReportDetailsPage.tsx @@ -5,7 +5,6 @@ import type {OnyxEntry} from 'react-native-onyx'; import type {ValueOf} from 'type-fest'; import AvatarWithImagePicker from '@components/AvatarWithImagePicker'; import FullPageNotFoundView from '@components/BlockingViews/FullPageNotFoundView'; -import DisplayNames from '@components/DisplayNames'; import HeaderWithBackButton from '@components/HeaderWithBackButton'; import MentionReportContext from '@components/HTMLEngineProvider/HTMLRenderers/MentionReportRenderer/MentionReportContext'; import MenuItem from '@components/MenuItem'; @@ -13,7 +12,6 @@ import MenuItemWithTopDescription from '@components/MenuItemWithTopDescription'; import {ModalActions} from '@components/Modal/Global/ModalContext'; import OfflineWithFeedback from '@components/OfflineWithFeedback'; import ParentNavigationSubtitle from '@components/ParentNavigationSubtitle'; -import PressableWithoutFeedback from '@components/Pressable/PressableWithoutFeedback'; import type {PromotedAction} from '@components/PromotedActionsBar'; import PromotedActionsBar, {PromotedActions} from '@components/PromotedActionsBar'; import ReportActionAvatars from '@components/ReportActionAvatars'; @@ -40,13 +38,13 @@ import usePreferredPolicy from '@hooks/usePreferredPolicy'; import useReportAttributes from '@hooks/useReportAttributes'; import useReportIsArchived from '@hooks/useReportIsArchived'; import useResponsiveLayout from '@hooks/useResponsiveLayout'; +import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; import getBase62ReportID from '@libs/getBase62ReportID'; import getNonEmptyStringOnyxID from '@libs/getNonEmptyStringOnyxID'; import Navigation, {navigationRef} from '@libs/Navigation/Navigation'; import type {PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types'; import type {ReportDetailsNavigatorParamList, RightModalNavigatorParamList} from '@libs/Navigation/types'; -import {getPersonalDetailsForAccountIDs} from '@libs/OptionsListUtils'; import Parser from '@libs/Parser'; import Permissions from '@libs/Permissions'; import {isPaidGroupPolicy, isPolicyAdmin as isPolicyAdminUtil, isPolicyEmployee as isPolicyEmployeeUtil, shouldShowPolicy} from '@libs/PolicyUtils'; @@ -62,7 +60,6 @@ import { createDraftTransactionAndNavigateToParticipantSelector, getAvailableReportFields, getChatRoomSubtitle, - getDisplayNamesWithTooltips, getIcons, getOriginalReportID, getParentNavigationSubtitle, @@ -104,10 +101,10 @@ import { navigateBackOnDeleteTransaction, navigateToPrivateNotes, shouldDisableRename as shouldDisableRenameUtil, - shouldUseFullTitleToDisplay, } from '@libs/ReportUtils'; import StringUtils from '@libs/StringUtils'; import {isDemoTransaction} from '@libs/TransactionUtils'; +import variables from '@styles/variables'; import {deleteTrackExpense, getNavigationUrlAfterTrackExpenseDelete, getNavigationUrlOnMoneyRequestDelete} from '@userActions/IOU'; import { clearAvatarErrors, @@ -156,9 +153,10 @@ const CASES = { type CaseID = ValueOf; function ReportDetailsPage({policy, report, route, reportMetadata}: ReportDetailsPageProps) { - const {translate, localeCompare, formatPhoneNumber} = useLocalize(); + const {translate, formatPhoneNumber} = useLocalize(); const {isOffline} = useNetwork(); const {isRestrictedToPreferredPolicy, preferredPolicyID} = usePreferredPolicy(); + const theme = useTheme(); const activePolicy = useActivePolicy(); const styles = useThemeStyles(); const expensifyIcons = useMemoizedLazyExpensifyIcons(['Users', 'Gear', 'Send', 'Folder', 'UserPlus', 'Pencil', 'Checkmark', 'Building', 'Exit', 'Bug', 'Camera', 'Trashcan']); @@ -197,7 +195,7 @@ function ReportDetailsPage({policy, report, route, reportMetadata}: ReportDetail const isPolicyAdmin = useMemo(() => isPolicyAdminUtil(policy), [policy]); const isPolicyEmployee = useMemo(() => isPolicyEmployeeUtil(report?.policyID, policy), [report?.policyID, policy]); const isPolicyExpenseChat = useMemo(() => isPolicyExpenseChatUtil(report), [report]); - const shouldUseFullTitle = useMemo(() => shouldUseFullTitleToDisplay(report), [report]); + const isChatRoom = useMemo(() => isChatRoomUtil(report), [report]); const isUserCreatedPolicyRoom = useMemo(() => isUserCreatedPolicyRoomUtil(report), [report]); const isDefaultRoom = useMemo(() => isDefaultRoomUtil(report), [report]); @@ -225,6 +223,7 @@ function ReportDetailsPage({policy, report, route, reportMetadata}: ReportDetail const parentNavigationSubtitleData = getParentNavigationSubtitle(report, isParentReportArchived); const base62ReportID = getBase62ReportID(Number(report.reportID)); const ancestors = useAncestors(report); + const parentNavigationSubtitleTextStyle = useMemo(() => ({fontSize: variables.fontSizeNormal, color: theme.heading}), [theme.heading]); // eslint-disable-next-line react-hooks/exhaustive-deps -- policy is a dependency because `getChatRoomSubtitle` calls `getPolicyName` which in turn retrieves the value from the `policy` value stored in Onyx const chatRoomSubtitle = useMemo(() => { const subtitle = getChatRoomSubtitle(report, false, isReportArchived); @@ -630,26 +629,11 @@ function ReportDetailsPage({policy, report, route, reportMetadata}: ReportDetail userBillingGraceEndPeriodCollection, ]); - const displayNamesWithTooltips = useMemo(() => { - const hasMultipleParticipants = participants.length > 1; - return getDisplayNamesWithTooltips(getPersonalDetailsForAccountIDs(participants, personalDetails), hasMultipleParticipants, localeCompare, formatPhoneNumber); - }, [participants, personalDetails, localeCompare, formatPhoneNumber]); - const icons = useMemo( () => getIcons(report, formatPhoneNumber, personalDetails, null, '', -1, policy, undefined, isReportArchived), [report, formatPhoneNumber, personalDetails, policy, isReportArchived], ); - const chatRoomSubtitleText = chatRoomSubtitle ? ( - - ) : null; - const renderedAvatar = useMemo(() => { if (isChatRoom && !isThread) { return ( @@ -737,61 +721,36 @@ function ReportDetailsPage({policy, report, route, reportMetadata}: ReportDetail }, [canJoin, report, backTo, currentUserPersonalDetails.accountID]); const nameSectionExpenseIOU = ( - - {shouldDisableRename && ( - <> - - - - {isPolicyAdmin ? ( - { - let policyID = report?.policyID; - - if (!policyID) { - policyID = ''; - } - - Navigation.navigate(ROUTES.WORKSPACE_INITIAL.getRoute(policyID)); - }} - > - {chatRoomSubtitleText} - - ) : ( - chatRoomSubtitleText - )} - - )} + <> + {!isEmptyObject(parentNavigationSubtitleData) && (isMoneyRequestReport || isInvoiceReport || isMoneyRequest || isTaskReport) && ( - - + - - + } + description={translate('threads.from')} + descriptionTextStyle={[styles.mutedNormalTextLabel, styles.mb1]} + shouldCheckActionAllowedOnPress={false} + /> )} - + ); const nameSectionGroupWorkspace = ( @@ -839,6 +798,8 @@ function ReportDetailsPage({policy, report, route, reportMetadata}: ReportDetail parentReportActionID={report?.parentReportActionID} pressableStyles={[styles.mt1, styles.mw100]} subtitleNumberOfLines={2} + shouldShowFrom={false} + textStyles={parentNavigationSubtitleTextStyle} /> ); @@ -867,7 +828,13 @@ function ReportDetailsPage({policy, report, route, reportMetadata}: ReportDetail Navigation.navigate(ROUTES.EDIT_REPORT_FIELD_REQUEST.getRoute(report.reportID, policyID, CONST.REPORT_FIELD_TITLE_FIELD_ID, backTo)); }} - furtherDetailsComponent={nameSectionFurtherDetailsContent} + /> + @@ -1026,11 +993,9 @@ function ReportDetailsPage({policy, report, route, reportMetadata}: ReportDetail onBackButtonPress={() => Navigation.goBack(backTo)} /> - - {renderedAvatar} - {isExpenseReport && !shouldShowEditableTitleField && nameSectionExpenseIOU} - - {isExpenseReport && shouldShowEditableTitleField && nameSectionTitleField} + {renderedAvatar} + {isExpenseReport && (!shouldShowEditableTitleField || !titleField) && nameSectionExpenseIOU} + {isExpenseReport && shouldShowEditableTitleField && titleField && nameSectionTitleField} {!isExpenseReport && nameSectionGroupWorkspace}