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}