From 3802fa43cc567c299e19bae8fd704e512f5afaea Mon Sep 17 00:00:00 2001 From: rory Date: Tue, 5 May 2026 18:36:34 -0700 Subject: [PATCH 1/5] refactor(contextmenu): derive isChronosReport internally MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the isChronosReport prop from BaseReportActionContextMenu, PopoverReportActionContextMenu, and the showContextMenu() public API. Derive it inside BaseReportActionContextMenu using the already-imported chatIncludesChronosWithID(originalReportID) — the same call that was already used in openOverflowMenu for the overflow submenu case. Remove isChronos from openOverflowMenu's showContextMenu call since it was always chatIncludesChronosWithID(originalReportID), identical to the new derived value. Remove isChronosReport from MiniReportActionContextMenu and the showPopover call in PureReportActionItem. Co-authored-by: Cursor --- .../report/ContextMenu/BaseReportActionContextMenu.tsx | 6 +----- .../report/ContextMenu/PopoverReportActionContextMenu.tsx | 5 +---- .../inbox/report/ContextMenu/ReportActionContextMenu.ts | 2 -- src/pages/inbox/report/PureReportActionItem.tsx | 3 --- 4 files changed, 2 insertions(+), 14 deletions(-) diff --git a/src/pages/inbox/report/ContextMenu/BaseReportActionContextMenu.tsx b/src/pages/inbox/report/ContextMenu/BaseReportActionContextMenu.tsx index 23a3cc766fe4..30becdd1fe47 100755 --- a/src/pages/inbox/report/ContextMenu/BaseReportActionContextMenu.tsx +++ b/src/pages/inbox/report/ContextMenu/BaseReportActionContextMenu.tsx @@ -83,9 +83,6 @@ type BaseReportActionContextMenuProps = { /** Target node which is the target of ContentMenu */ anchor?: RefObject; - /** Flag to check if the chat participant is Chronos */ - isChronosReport?: boolean; - /** Whether the provided report is an archived room */ isArchivedRoom?: boolean; @@ -118,7 +115,6 @@ function BaseReportActionContextMenu({ type = CONST.CONTEXT_MENU_TYPES.REPORT_ACTION, anchor, contentRef, - isChronosReport = false, isArchivedRoom = false, isMini = false, isVisible = false, @@ -261,6 +257,7 @@ function BaseReportActionContextMenu({ isMoneyRequestOrReport && !isArchivedNonExpenseReport(transactionThreadReportID ? childReport : parentReport, transactionThreadReportID ? isChildReportArchived : isParentReportArchived); + const isChronosReport = chatIncludesChronosWithID(originalReportID); const shouldEnableArrowNavigation = !isMini && (isVisible || shouldKeepOpen); const isHarvestReport = isHarvestCreatedExpenseReport(reportNameValuePairs?.origin, reportNameValuePairs?.originalID); @@ -347,7 +344,6 @@ function BaseReportActionContextMenu({ reportID, originalReportID, isArchivedRoom: isArchivedNonExpenseReport(originalReport, isOriginalReportArchived), - isChronos: chatIncludesChronosWithID(originalReportID), }, reportAction: { reportActionID: reportAction?.reportActionID, diff --git a/src/pages/inbox/report/ContextMenu/PopoverReportActionContextMenu.tsx b/src/pages/inbox/report/ContextMenu/PopoverReportActionContextMenu.tsx index 7730e8b655e0..de2599ebdc81 100644 --- a/src/pages/inbox/report/ContextMenu/PopoverReportActionContextMenu.tsx +++ b/src/pages/inbox/report/ContextMenu/PopoverReportActionContextMenu.tsx @@ -85,7 +85,6 @@ function PopoverReportActionContextMenu({ref}: PopoverReportActionContextMenuPro const [shouldSetModalVisibilityForDeleteConfirmation, setShouldSetModalVisibilityForDeleteConfirmation] = useState(true); const [isRoomArchived, setIsRoomArchived] = useState(false); - const [isChronosReportEnabled, setIsChronosReportEnabled] = useState(false); const [isChatPinned, setIsChatPinned] = useState(false); const [hasUnreadMessages, setHasUnreadMessages] = useState(false); const [isThreadReportParentAction, setIsThreadReportParentAction] = useState(false); @@ -207,7 +206,7 @@ function PopoverReportActionContextMenu({ref}: PopoverReportActionContextMenuPro setComposerToRefocusOnClose('edit'); } - const {reportID, originalReportID, isArchivedRoom = false, isChronos = false, isPinnedChat = false, isUnreadChat = false} = currentReport; + const {reportID, originalReportID, isArchivedRoom = false, isPinnedChat = false, isUnreadChat = false} = currentReport; const {reportActionID, draftMessage, isThreadReportParentAction: isThreadReportParentActionParam = false} = reportAction; const {onShow = () => {}, onHide = () => {}, setIsEmojiPickerActive = () => {}} = callbacks; setIsContextMenuOpening(true); @@ -256,7 +255,6 @@ function PopoverReportActionContextMenu({ref}: PopoverReportActionContextMenuPro setIsPopoverVisible(true); reportActionDraftMessageRef.current = draftMessage; setIsRoomArchived(isArchivedRoom); - setIsChronosReportEnabled(isChronos); setIsChatPinned(isPinnedChat); setHasUnreadMessages(isUnreadChat); setIsThreadReportParentAction(isThreadReportParentActionParam); @@ -511,7 +509,6 @@ function PopoverReportActionContextMenu({ref}: PopoverReportActionContextMenuPro draftMessage={reportActionDraftMessageRef.current} selection={selectionRef.current} isArchivedRoom={isRoomArchived} - isChronosReport={isChronosReportEnabled} isPinnedChat={isChatPinned} isUnreadChat={hasUnreadMessages} isThreadReportParentAction={isThreadReportParentAction} diff --git a/src/pages/inbox/report/ContextMenu/ReportActionContextMenu.ts b/src/pages/inbox/report/ContextMenu/ReportActionContextMenu.ts index 9aff6d7013b5..3808a3735f60 100644 --- a/src/pages/inbox/report/ContextMenu/ReportActionContextMenu.ts +++ b/src/pages/inbox/report/ContextMenu/ReportActionContextMenu.ts @@ -26,7 +26,6 @@ type ShowContextMenuParams = { reportID?: string; originalReportID?: string; isArchivedRoom?: boolean; - isChronos?: boolean; isPinnedChat?: boolean; isUnreadChat?: boolean; }; @@ -125,7 +124,6 @@ function hideContextMenu(shouldDelay?: boolean, onHideCallback = () => {}, param * @param [onShow=() => {}] - Run a callback when Menu is shown * @param [onHide=() => {}] - Run a callback when Menu is hidden * @param isArchivedRoom - Whether the provided report is an archived room - * @param isChronosReport - Flag to check if the chat participant is Chronos * @param isPinnedChat - Flag to check if the chat is pinned in the LHN. Used for the Pin/Unpin action * @param isUnreadChat - Flag to check if the chat has unread messages in the LHN. Used for the Mark as Read/Unread action */ diff --git a/src/pages/inbox/report/PureReportActionItem.tsx b/src/pages/inbox/report/PureReportActionItem.tsx index 439341c49600..17cbbd962b75 100644 --- a/src/pages/inbox/report/PureReportActionItem.tsx +++ b/src/pages/inbox/report/PureReportActionItem.tsx @@ -552,7 +552,6 @@ function PureReportActionItem({ reportID, originalReportID, isArchivedRoom, - isChronos: isChronosReport, }, reportAction: { reportActionID: action.reportActionID, @@ -578,7 +577,6 @@ function PureReportActionItem({ shouldDisplayContextMenuValue, disabledActions, isArchivedRoom, - isChronosReport, handleShowContextMenu, isThreadReportParentAction, ], @@ -1149,7 +1147,6 @@ function PureReportActionItem({ isVisible={hovered && draftMessage === undefined && !hasErrors} isThreadReportParentAction={isThreadReportParentAction} draftMessage={draftMessage} - isChronosReport={isChronosReport} checkIfContextMenuActive={toggleContextMenuFromActiveReportAction} setIsEmojiPickerActive={setIsEmojiPickerActive} /> From 26d0cfa4a11579a2ab9090dfe57c3df647a16673 Mon Sep 17 00:00:00 2001 From: rory Date: Tue, 5 May 2026 18:37:25 -0700 Subject: [PATCH 2/5] refactor(contextmenu): derive isPinnedChat internally Remove the isPinnedChat prop from BaseReportActionContextMenu, PopoverReportActionContextMenu, and the showContextMenu() public API. Derive it inside BaseReportActionContextMenu as !!report?.isPinned, using the report object already subscribed to via useOnyx. Remove isPinnedChat from OptionRowPressable's showContextMenu call. Co-authored-by: Cursor --- src/components/LHNOptionsList/OptionRowPressable.tsx | 1 - .../inbox/report/ContextMenu/BaseReportActionContextMenu.tsx | 5 +---- .../report/ContextMenu/PopoverReportActionContextMenu.tsx | 5 +---- .../inbox/report/ContextMenu/ReportActionContextMenu.ts | 2 -- 4 files changed, 2 insertions(+), 11 deletions(-) diff --git a/src/components/LHNOptionsList/OptionRowPressable.tsx b/src/components/LHNOptionsList/OptionRowPressable.tsx index d6bb4d6e0df6..81a55d158249 100644 --- a/src/components/LHNOptionsList/OptionRowPressable.tsx +++ b/src/components/LHNOptionsList/OptionRowPressable.tsx @@ -59,7 +59,6 @@ function OptionRowPressable({ report: { reportID, originalReportID: reportID, - isPinnedChat: optionItem.isPinned, isUnreadChat: !!optionItem.isUnread, }, reportAction: { diff --git a/src/pages/inbox/report/ContextMenu/BaseReportActionContextMenu.tsx b/src/pages/inbox/report/ContextMenu/BaseReportActionContextMenu.tsx index 30becdd1fe47..922562d3956e 100755 --- a/src/pages/inbox/report/ContextMenu/BaseReportActionContextMenu.tsx +++ b/src/pages/inbox/report/ContextMenu/BaseReportActionContextMenu.tsx @@ -86,9 +86,6 @@ type BaseReportActionContextMenuProps = { /** Whether the provided report is an archived room */ isArchivedRoom?: boolean; - /** Flag to check if the chat is pinned in the LHN. Used for the Pin/Unpin action */ - isPinnedChat?: boolean; - /** Flag to check if the chat is unread in the LHN. Used for the Mark as Read/Unread action */ isUnreadChat?: boolean; @@ -118,7 +115,6 @@ function BaseReportActionContextMenu({ isArchivedRoom = false, isMini = false, isVisible = false, - isPinnedChat = false, isUnreadChat = false, isThreadReportParentAction = false, selection = '', @@ -258,6 +254,7 @@ function BaseReportActionContextMenu({ !isArchivedNonExpenseReport(transactionThreadReportID ? childReport : parentReport, transactionThreadReportID ? isChildReportArchived : isParentReportArchived); const isChronosReport = chatIncludesChronosWithID(originalReportID); + const isPinnedChat = !!report?.isPinned; const shouldEnableArrowNavigation = !isMini && (isVisible || shouldKeepOpen); const isHarvestReport = isHarvestCreatedExpenseReport(reportNameValuePairs?.origin, reportNameValuePairs?.originalID); diff --git a/src/pages/inbox/report/ContextMenu/PopoverReportActionContextMenu.tsx b/src/pages/inbox/report/ContextMenu/PopoverReportActionContextMenu.tsx index de2599ebdc81..b7052babbb53 100644 --- a/src/pages/inbox/report/ContextMenu/PopoverReportActionContextMenu.tsx +++ b/src/pages/inbox/report/ContextMenu/PopoverReportActionContextMenu.tsx @@ -85,7 +85,6 @@ function PopoverReportActionContextMenu({ref}: PopoverReportActionContextMenuPro const [shouldSetModalVisibilityForDeleteConfirmation, setShouldSetModalVisibilityForDeleteConfirmation] = useState(true); const [isRoomArchived, setIsRoomArchived] = useState(false); - const [isChatPinned, setIsChatPinned] = useState(false); const [hasUnreadMessages, setHasUnreadMessages] = useState(false); const [isThreadReportParentAction, setIsThreadReportParentAction] = useState(false); const [disabledActions, setDisabledActions] = useState([]); @@ -206,7 +205,7 @@ function PopoverReportActionContextMenu({ref}: PopoverReportActionContextMenuPro setComposerToRefocusOnClose('edit'); } - const {reportID, originalReportID, isArchivedRoom = false, isPinnedChat = false, isUnreadChat = false} = currentReport; + const {reportID, originalReportID, isArchivedRoom = false, isUnreadChat = false} = currentReport; const {reportActionID, draftMessage, isThreadReportParentAction: isThreadReportParentActionParam = false} = reportAction; const {onShow = () => {}, onHide = () => {}, setIsEmojiPickerActive = () => {}} = callbacks; setIsContextMenuOpening(true); @@ -255,7 +254,6 @@ function PopoverReportActionContextMenu({ref}: PopoverReportActionContextMenuPro setIsPopoverVisible(true); reportActionDraftMessageRef.current = draftMessage; setIsRoomArchived(isArchivedRoom); - setIsChatPinned(isPinnedChat); setHasUnreadMessages(isUnreadChat); setIsThreadReportParentAction(isThreadReportParentActionParam); setShouldSwitchPositionIfOverflow(isOverflowMenu); @@ -509,7 +507,6 @@ function PopoverReportActionContextMenu({ref}: PopoverReportActionContextMenuPro draftMessage={reportActionDraftMessageRef.current} selection={selectionRef.current} isArchivedRoom={isRoomArchived} - isPinnedChat={isChatPinned} isUnreadChat={hasUnreadMessages} isThreadReportParentAction={isThreadReportParentAction} anchor={contextMenuTargetNode} diff --git a/src/pages/inbox/report/ContextMenu/ReportActionContextMenu.ts b/src/pages/inbox/report/ContextMenu/ReportActionContextMenu.ts index 3808a3735f60..bb6a3cd0e72b 100644 --- a/src/pages/inbox/report/ContextMenu/ReportActionContextMenu.ts +++ b/src/pages/inbox/report/ContextMenu/ReportActionContextMenu.ts @@ -26,7 +26,6 @@ type ShowContextMenuParams = { reportID?: string; originalReportID?: string; isArchivedRoom?: boolean; - isPinnedChat?: boolean; isUnreadChat?: boolean; }; reportAction?: { @@ -124,7 +123,6 @@ function hideContextMenu(shouldDelay?: boolean, onHideCallback = () => {}, param * @param [onShow=() => {}] - Run a callback when Menu is shown * @param [onHide=() => {}] - Run a callback when Menu is hidden * @param isArchivedRoom - Whether the provided report is an archived room - * @param isPinnedChat - Flag to check if the chat is pinned in the LHN. Used for the Pin/Unpin action * @param isUnreadChat - Flag to check if the chat has unread messages in the LHN. Used for the Mark as Read/Unread action */ function showContextMenu(showContextMenuParams: ShowContextMenuParams) { From f89fb324ebeb56778ffccf8a2f61c787304e2a81 Mon Sep 17 00:00:00 2001 From: rory Date: Tue, 5 May 2026 18:38:13 -0700 Subject: [PATCH 3/5] refactor(contextmenu): derive isUnreadChat internally Remove the isUnreadChat prop from BaseReportActionContextMenu, PopoverReportActionContextMenu, and the showContextMenu() public API. Derive it inside BaseReportActionContextMenu by comparing report.lastReadTime against report.lastVisibleActionCreated, using the report already subscribed to via useOnyx. Remove isUnreadChat from OptionRowPressable's showContextMenu call. Co-authored-by: Cursor --- src/components/LHNOptionsList/OptionRowPressable.tsx | 1 - .../inbox/report/ContextMenu/BaseReportActionContextMenu.tsx | 5 +---- .../report/ContextMenu/PopoverReportActionContextMenu.tsx | 5 +---- .../inbox/report/ContextMenu/ReportActionContextMenu.ts | 2 -- 4 files changed, 2 insertions(+), 11 deletions(-) diff --git a/src/components/LHNOptionsList/OptionRowPressable.tsx b/src/components/LHNOptionsList/OptionRowPressable.tsx index 81a55d158249..e5260999184a 100644 --- a/src/components/LHNOptionsList/OptionRowPressable.tsx +++ b/src/components/LHNOptionsList/OptionRowPressable.tsx @@ -59,7 +59,6 @@ function OptionRowPressable({ report: { reportID, originalReportID: reportID, - isUnreadChat: !!optionItem.isUnread, }, reportAction: { reportActionID: '-1', diff --git a/src/pages/inbox/report/ContextMenu/BaseReportActionContextMenu.tsx b/src/pages/inbox/report/ContextMenu/BaseReportActionContextMenu.tsx index 922562d3956e..528c5412a966 100755 --- a/src/pages/inbox/report/ContextMenu/BaseReportActionContextMenu.tsx +++ b/src/pages/inbox/report/ContextMenu/BaseReportActionContextMenu.tsx @@ -86,9 +86,6 @@ type BaseReportActionContextMenuProps = { /** Whether the provided report is an archived room */ isArchivedRoom?: boolean; - /** Flag to check if the chat is unread in the LHN. Used for the Mark as Read/Unread action */ - isUnreadChat?: boolean; - /** * Is the action a thread's parent reportAction viewed from within the thread report? * It will be false if we're viewing the same parent report action from the report it belongs to rather than the thread. @@ -115,7 +112,6 @@ function BaseReportActionContextMenu({ isArchivedRoom = false, isMini = false, isVisible = false, - isUnreadChat = false, isThreadReportParentAction = false, selection = '', draftMessage = '', @@ -255,6 +251,7 @@ function BaseReportActionContextMenu({ const isChronosReport = chatIncludesChronosWithID(originalReportID); const isPinnedChat = !!report?.isPinned; + const isUnreadChat = !report?.lastReadTime || report.lastReadTime < (report.lastVisibleActionCreated ?? ''); const shouldEnableArrowNavigation = !isMini && (isVisible || shouldKeepOpen); const isHarvestReport = isHarvestCreatedExpenseReport(reportNameValuePairs?.origin, reportNameValuePairs?.originalID); diff --git a/src/pages/inbox/report/ContextMenu/PopoverReportActionContextMenu.tsx b/src/pages/inbox/report/ContextMenu/PopoverReportActionContextMenu.tsx index b7052babbb53..0b2c082ef32a 100644 --- a/src/pages/inbox/report/ContextMenu/PopoverReportActionContextMenu.tsx +++ b/src/pages/inbox/report/ContextMenu/PopoverReportActionContextMenu.tsx @@ -85,7 +85,6 @@ function PopoverReportActionContextMenu({ref}: PopoverReportActionContextMenuPro const [shouldSetModalVisibilityForDeleteConfirmation, setShouldSetModalVisibilityForDeleteConfirmation] = useState(true); const [isRoomArchived, setIsRoomArchived] = useState(false); - const [hasUnreadMessages, setHasUnreadMessages] = useState(false); const [isThreadReportParentAction, setIsThreadReportParentAction] = useState(false); const [disabledActions, setDisabledActions] = useState([]); const [shouldSwitchPositionIfOverflow, setShouldSwitchPositionIfOverflow] = useState(false); @@ -205,7 +204,7 @@ function PopoverReportActionContextMenu({ref}: PopoverReportActionContextMenuPro setComposerToRefocusOnClose('edit'); } - const {reportID, originalReportID, isArchivedRoom = false, isUnreadChat = false} = currentReport; + const {reportID, originalReportID, isArchivedRoom = false} = currentReport; const {reportActionID, draftMessage, isThreadReportParentAction: isThreadReportParentActionParam = false} = reportAction; const {onShow = () => {}, onHide = () => {}, setIsEmojiPickerActive = () => {}} = callbacks; setIsContextMenuOpening(true); @@ -254,7 +253,6 @@ function PopoverReportActionContextMenu({ref}: PopoverReportActionContextMenuPro setIsPopoverVisible(true); reportActionDraftMessageRef.current = draftMessage; setIsRoomArchived(isArchivedRoom); - setHasUnreadMessages(isUnreadChat); setIsThreadReportParentAction(isThreadReportParentActionParam); setShouldSwitchPositionIfOverflow(isOverflowMenu); }); @@ -507,7 +505,6 @@ function PopoverReportActionContextMenu({ref}: PopoverReportActionContextMenuPro draftMessage={reportActionDraftMessageRef.current} selection={selectionRef.current} isArchivedRoom={isRoomArchived} - isUnreadChat={hasUnreadMessages} isThreadReportParentAction={isThreadReportParentAction} anchor={contextMenuTargetNode} contentRef={contentRef} diff --git a/src/pages/inbox/report/ContextMenu/ReportActionContextMenu.ts b/src/pages/inbox/report/ContextMenu/ReportActionContextMenu.ts index bb6a3cd0e72b..79f8be732205 100644 --- a/src/pages/inbox/report/ContextMenu/ReportActionContextMenu.ts +++ b/src/pages/inbox/report/ContextMenu/ReportActionContextMenu.ts @@ -26,7 +26,6 @@ type ShowContextMenuParams = { reportID?: string; originalReportID?: string; isArchivedRoom?: boolean; - isUnreadChat?: boolean; }; reportAction?: { reportActionID?: string; @@ -123,7 +122,6 @@ function hideContextMenu(shouldDelay?: boolean, onHideCallback = () => {}, param * @param [onShow=() => {}] - Run a callback when Menu is shown * @param [onHide=() => {}] - Run a callback when Menu is hidden * @param isArchivedRoom - Whether the provided report is an archived room - * @param isUnreadChat - Flag to check if the chat has unread messages in the LHN. Used for the Mark as Read/Unread action */ function showContextMenu(showContextMenuParams: ShowContextMenuParams) { if (!contextMenuRef.current) { From f259145ba6b5c03b7679964f2383de09d98b5aae Mon Sep 17 00:00:00 2001 From: rory Date: Tue, 5 May 2026 18:39:19 -0700 Subject: [PATCH 4/5] refactor(contextmenu): derive isThreadReportParentAction internally MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove the isThreadReportParentAction prop from BaseReportActionContextMenu, PopoverReportActionContextMenu, and the showContextMenu() public API. Derive it inside BaseReportActionContextMenu by checking whether the reportAction's childReportID matches the current reportID — this is true exactly when we're viewing the parent action from within its thread report. Remove isThreadReportParentAction from MiniReportActionContextMenu and the showPopover call in PureReportActionItem. Remove it from openOverflowMenu's showContextMenu call since the overflow context menu will re-derive it internally from the same condition. Co-authored-by: Cursor --- .../ContextMenu/BaseReportActionContextMenu.tsx | 10 ++-------- .../ContextMenu/PopoverReportActionContextMenu.tsx | 11 +---------- .../report/ContextMenu/ReportActionContextMenu.ts | 1 - src/pages/inbox/report/PureReportActionItem.tsx | 8 -------- src/pages/inbox/report/ReportActionItem.tsx | 3 +-- 5 files changed, 4 insertions(+), 29 deletions(-) diff --git a/src/pages/inbox/report/ContextMenu/BaseReportActionContextMenu.tsx b/src/pages/inbox/report/ContextMenu/BaseReportActionContextMenu.tsx index 528c5412a966..3f8c90e578e2 100755 --- a/src/pages/inbox/report/ContextMenu/BaseReportActionContextMenu.tsx +++ b/src/pages/inbox/report/ContextMenu/BaseReportActionContextMenu.tsx @@ -86,12 +86,6 @@ type BaseReportActionContextMenuProps = { /** Whether the provided report is an archived room */ isArchivedRoom?: boolean; - /** - * Is the action a thread's parent reportAction viewed from within the thread report? - * It will be false if we're viewing the same parent report action from the report it belongs to rather than the thread. - */ - isThreadReportParentAction?: boolean; - /** Content Ref */ contentRef?: RefObject; @@ -112,7 +106,6 @@ function BaseReportActionContextMenu({ isArchivedRoom = false, isMini = false, isVisible = false, - isThreadReportParentAction = false, selection = '', draftMessage = '', reportActionID, @@ -252,6 +245,8 @@ function BaseReportActionContextMenu({ const isChronosReport = chatIncludesChronosWithID(originalReportID); const isPinnedChat = !!report?.isPinned; const isUnreadChat = !report?.lastReadTime || report.lastReadTime < (report.lastVisibleActionCreated ?? ''); + // True when this action is the parent of a thread and we're viewing from within that thread + const isThreadReportParentAction = !!reportAction?.childReportID && String(reportAction.childReportID) === reportID; const shouldEnableArrowNavigation = !isMini && (isVisible || shouldKeepOpen); const isHarvestReport = isHarvestCreatedExpenseReport(reportNameValuePairs?.origin, reportNameValuePairs?.originalID); @@ -342,7 +337,6 @@ function BaseReportActionContextMenu({ reportAction: { reportActionID: reportAction?.reportActionID, draftMessage, - isThreadReportParentAction, }, callbacks: { onShow: checkIfContextMenuActive, diff --git a/src/pages/inbox/report/ContextMenu/PopoverReportActionContextMenu.tsx b/src/pages/inbox/report/ContextMenu/PopoverReportActionContextMenu.tsx index 0b2c082ef32a..b24ec90f8e73 100644 --- a/src/pages/inbox/report/ContextMenu/PopoverReportActionContextMenu.tsx +++ b/src/pages/inbox/report/ContextMenu/PopoverReportActionContextMenu.tsx @@ -85,7 +85,6 @@ function PopoverReportActionContextMenu({ref}: PopoverReportActionContextMenuPro const [shouldSetModalVisibilityForDeleteConfirmation, setShouldSetModalVisibilityForDeleteConfirmation] = useState(true); const [isRoomArchived, setIsRoomArchived] = useState(false); - const [isThreadReportParentAction, setIsThreadReportParentAction] = useState(false); const [disabledActions, setDisabledActions] = useState([]); const [shouldSwitchPositionIfOverflow, setShouldSwitchPositionIfOverflow] = useState(false); const [isWithoutOverlay, setIsWithoutOverlay] = useState(true); @@ -179,9 +178,6 @@ function PopoverReportActionContextMenu({ref}: PopoverReportActionContextMenuPro * @param [onShow] - Run a callback when Menu is shown * @param [onHide] - Run a callback when Menu is hidden * @param isArchivedRoom - Whether the provided report is an archived room - * @param isChronosReport - Flag to check if the chat participant is Chronos - * @param isPinnedChat - Flag to check if the chat is pinned in the LHN. Used for the Pin/Unpin action - * @param isUnreadChat - Flag to check if the chat is unread in the LHN. Used for the Mark as Read/Unread action */ const showContextMenu: ReportActionContextMenu['showContextMenu'] = (showContextMenuParams) => { cancelAnimation(hideDelayProgress); @@ -205,7 +201,7 @@ function PopoverReportActionContextMenu({ref}: PopoverReportActionContextMenuPro } const {reportID, originalReportID, isArchivedRoom = false} = currentReport; - const {reportActionID, draftMessage, isThreadReportParentAction: isThreadReportParentActionParam = false} = reportAction; + const {reportActionID, draftMessage} = reportAction; const {onShow = () => {}, onHide = () => {}, setIsEmojiPickerActive = () => {}} = callbacks; setIsContextMenuOpening(true); setIsWithoutOverlay(withoutOverlay); @@ -253,7 +249,6 @@ function PopoverReportActionContextMenu({ref}: PopoverReportActionContextMenuPro setIsPopoverVisible(true); reportActionDraftMessageRef.current = draftMessage; setIsRoomArchived(isArchivedRoom); - setIsThreadReportParentAction(isThreadReportParentActionParam); setShouldSwitchPositionIfOverflow(isOverflowMenu); }); }; @@ -447,9 +442,6 @@ function PopoverReportActionContextMenu({ref}: PopoverReportActionContextMenuPro setIsDeleteCommentConfirmModalVisible(false); setShouldSetModalVisibilityForDeleteConfirmation(true); setIsRoomArchived(false); - setIsChronosReportEnabled(false); - setIsChatPinned(false); - setHasUnreadMessages(false); }; /** Opens the Confirm delete action modal */ @@ -505,7 +497,6 @@ function PopoverReportActionContextMenu({ref}: PopoverReportActionContextMenuPro draftMessage={reportActionDraftMessageRef.current} selection={selectionRef.current} isArchivedRoom={isRoomArchived} - isThreadReportParentAction={isThreadReportParentAction} anchor={contextMenuTargetNode} contentRef={contentRef} originalReportID={originalReportIDRef.current} diff --git a/src/pages/inbox/report/ContextMenu/ReportActionContextMenu.ts b/src/pages/inbox/report/ContextMenu/ReportActionContextMenu.ts index 79f8be732205..a4457ccfc46a 100644 --- a/src/pages/inbox/report/ContextMenu/ReportActionContextMenu.ts +++ b/src/pages/inbox/report/ContextMenu/ReportActionContextMenu.ts @@ -30,7 +30,6 @@ type ShowContextMenuParams = { reportAction?: { reportActionID?: string; draftMessage?: string; - isThreadReportParentAction?: boolean; }; callbacks?: { onShow?: () => void; diff --git a/src/pages/inbox/report/PureReportActionItem.tsx b/src/pages/inbox/report/PureReportActionItem.tsx index 17cbbd962b75..81fb902296d9 100644 --- a/src/pages/inbox/report/PureReportActionItem.tsx +++ b/src/pages/inbox/report/PureReportActionItem.tsx @@ -216,9 +216,6 @@ type PureReportActionItemProps = { /** Whether the room is archived */ isArchivedRoom?: boolean; - /** Whether the room is a chronos report */ - isChronosReport?: boolean; - /** Function to resolve actionable report mention whisper */ resolveActionableReportMentionWhisper?: ( report: OnyxEntry, @@ -303,7 +300,6 @@ function PureReportActionItem({ originalReport, deleteReportActionDraft = () => {}, isArchivedRoom, - isChronosReport, resolveActionableReportMentionWhisper = () => {}, resolveActionableMentionWhisper = () => {}, isClosedExpenseReportWithNoExpenses, @@ -556,7 +552,6 @@ function PureReportActionItem({ reportAction: { reportActionID: action.reportActionID, draftMessage, - isThreadReportParentAction, }, callbacks: { onShow: toggleContextMenuFromActiveReportAction, @@ -578,7 +573,6 @@ function PureReportActionItem({ disabledActions, isArchivedRoom, handleShowContextMenu, - isThreadReportParentAction, ], ); @@ -1145,7 +1139,6 @@ function PureReportActionItem({ displayAsGroup={displayAsGroup} disabledActions={disabledActions} isVisible={hovered && draftMessage === undefined && !hasErrors} - isThreadReportParentAction={isThreadReportParentAction} draftMessage={draftMessage} checkIfContextMenuActive={toggleContextMenuFromActiveReportAction} setIsEmojiPickerActive={setIsEmojiPickerActive} @@ -1232,7 +1225,6 @@ export default memo(PureReportActionItem, (prevProps, nextProps) => { prevProps.originalReportID === nextProps.originalReportID && deepEqual(prevProps.originalReport?.participants, nextProps.originalReport?.participants) && prevProps.isArchivedRoom === nextProps.isArchivedRoom && - prevProps.isChronosReport === nextProps.isChronosReport && prevProps.isClosedExpenseReportWithNoExpenses === nextProps.isClosedExpenseReportWithNoExpenses && prevProps.userBillingFundID === nextProps.userBillingFundID && prevProps.shouldHighlight === nextProps.shouldHighlight && diff --git a/src/pages/inbox/report/ReportActionItem.tsx b/src/pages/inbox/report/ReportActionItem.tsx index e36a20b65cfe..be86324d62b0 100644 --- a/src/pages/inbox/report/ReportActionItem.tsx +++ b/src/pages/inbox/report/ReportActionItem.tsx @@ -5,7 +5,7 @@ import useOriginalReportID from '@hooks/useOriginalReportID'; import useReportIsArchived from '@hooks/useReportIsArchived'; import useReportTransactions from '@hooks/useReportTransactions'; import {getIOUReportIDFromReportActionPreview, getOriginalMessage, isMoneyRequestAction} from '@libs/ReportActionsUtils'; -import {chatIncludesChronosWithID, getTransactionsWithReceipts, isArchivedNonExpenseReport, isClosedExpenseReportWithNoExpenses} from '@libs/ReportUtils'; +import {getTransactionsWithReceipts, isArchivedNonExpenseReport, isClosedExpenseReportWithNoExpenses} from '@libs/ReportUtils'; import {clearAllRelatedReportActionErrors} from '@userActions/ClearReportActionErrors'; import {deleteReportActionDraft, resolveActionableMentionWhisper, resolveActionableReportMentionWhisper} from '@userActions/Report'; import {clearError} from '@userActions/Transaction'; @@ -73,7 +73,6 @@ function ReportActionItem({ originalReport={originalReport} deleteReportActionDraft={deleteReportActionDraft} isArchivedRoom={isArchivedNonExpenseReport(originalReport, isOriginalReportArchived)} - isChronosReport={chatIncludesChronosWithID(originalReportID)} resolveActionableReportMentionWhisper={resolveActionableReportMentionWhisper} resolveActionableMentionWhisper={resolveActionableMentionWhisper} isClosedExpenseReportWithNoExpenses={isClosedExpenseReportWithNoExpenses(iouReport, transactionsOnIOUReport)} From 9630890c7ff64e7f7ec31df4c586cb2893d02f13 Mon Sep 17 00:00:00 2001 From: rory Date: Wed, 6 May 2026 00:35:44 -0700 Subject: [PATCH 5/5] revert: restore isThreadReportParentAction as a prop MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The derived implementation (reportAction.childReportID === reportID) was incorrect. ReportActionItemParentAction renders thread-header rows with report={ancestorReport} (the parent report), so reportID is the parent's ID, not the thread. childReportID points to the thread and never equals the parent reportID, causing the flag to always be false for thread-header rows — re-enabling Reply in thread and reversing the Join/Leave thread options for that case. Restore the prop so callers (PureReportActionItem, via the explicit isThreadReportParentAction prop it already receives) continue to pass the correct value through showContextMenu and the Popover state. Co-authored-by: Cursor --- .../report/ContextMenu/BaseReportActionContextMenu.tsx | 10 ++++++++-- .../ContextMenu/PopoverReportActionContextMenu.tsx | 5 ++++- .../report/ContextMenu/ReportActionContextMenu.ts | 1 + src/pages/inbox/report/PureReportActionItem.tsx | 3 +++ 4 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/pages/inbox/report/ContextMenu/BaseReportActionContextMenu.tsx b/src/pages/inbox/report/ContextMenu/BaseReportActionContextMenu.tsx index 3f8c90e578e2..528c5412a966 100755 --- a/src/pages/inbox/report/ContextMenu/BaseReportActionContextMenu.tsx +++ b/src/pages/inbox/report/ContextMenu/BaseReportActionContextMenu.tsx @@ -86,6 +86,12 @@ type BaseReportActionContextMenuProps = { /** Whether the provided report is an archived room */ isArchivedRoom?: boolean; + /** + * Is the action a thread's parent reportAction viewed from within the thread report? + * It will be false if we're viewing the same parent report action from the report it belongs to rather than the thread. + */ + isThreadReportParentAction?: boolean; + /** Content Ref */ contentRef?: RefObject; @@ -106,6 +112,7 @@ function BaseReportActionContextMenu({ isArchivedRoom = false, isMini = false, isVisible = false, + isThreadReportParentAction = false, selection = '', draftMessage = '', reportActionID, @@ -245,8 +252,6 @@ function BaseReportActionContextMenu({ const isChronosReport = chatIncludesChronosWithID(originalReportID); const isPinnedChat = !!report?.isPinned; const isUnreadChat = !report?.lastReadTime || report.lastReadTime < (report.lastVisibleActionCreated ?? ''); - // True when this action is the parent of a thread and we're viewing from within that thread - const isThreadReportParentAction = !!reportAction?.childReportID && String(reportAction.childReportID) === reportID; const shouldEnableArrowNavigation = !isMini && (isVisible || shouldKeepOpen); const isHarvestReport = isHarvestCreatedExpenseReport(reportNameValuePairs?.origin, reportNameValuePairs?.originalID); @@ -337,6 +342,7 @@ function BaseReportActionContextMenu({ reportAction: { reportActionID: reportAction?.reportActionID, draftMessage, + isThreadReportParentAction, }, callbacks: { onShow: checkIfContextMenuActive, diff --git a/src/pages/inbox/report/ContextMenu/PopoverReportActionContextMenu.tsx b/src/pages/inbox/report/ContextMenu/PopoverReportActionContextMenu.tsx index b24ec90f8e73..ecc465ad724a 100644 --- a/src/pages/inbox/report/ContextMenu/PopoverReportActionContextMenu.tsx +++ b/src/pages/inbox/report/ContextMenu/PopoverReportActionContextMenu.tsx @@ -85,6 +85,7 @@ function PopoverReportActionContextMenu({ref}: PopoverReportActionContextMenuPro const [shouldSetModalVisibilityForDeleteConfirmation, setShouldSetModalVisibilityForDeleteConfirmation] = useState(true); const [isRoomArchived, setIsRoomArchived] = useState(false); + const [isThreadReportParentAction, setIsThreadReportParentAction] = useState(false); const [disabledActions, setDisabledActions] = useState([]); const [shouldSwitchPositionIfOverflow, setShouldSwitchPositionIfOverflow] = useState(false); const [isWithoutOverlay, setIsWithoutOverlay] = useState(true); @@ -201,7 +202,7 @@ function PopoverReportActionContextMenu({ref}: PopoverReportActionContextMenuPro } const {reportID, originalReportID, isArchivedRoom = false} = currentReport; - const {reportActionID, draftMessage} = reportAction; + const {reportActionID, draftMessage, isThreadReportParentAction: isThreadReportParentActionParam = false} = reportAction; const {onShow = () => {}, onHide = () => {}, setIsEmojiPickerActive = () => {}} = callbacks; setIsContextMenuOpening(true); setIsWithoutOverlay(withoutOverlay); @@ -249,6 +250,7 @@ function PopoverReportActionContextMenu({ref}: PopoverReportActionContextMenuPro setIsPopoverVisible(true); reportActionDraftMessageRef.current = draftMessage; setIsRoomArchived(isArchivedRoom); + setIsThreadReportParentAction(isThreadReportParentActionParam); setShouldSwitchPositionIfOverflow(isOverflowMenu); }); }; @@ -497,6 +499,7 @@ function PopoverReportActionContextMenu({ref}: PopoverReportActionContextMenuPro draftMessage={reportActionDraftMessageRef.current} selection={selectionRef.current} isArchivedRoom={isRoomArchived} + isThreadReportParentAction={isThreadReportParentAction} anchor={contextMenuTargetNode} contentRef={contentRef} originalReportID={originalReportIDRef.current} diff --git a/src/pages/inbox/report/ContextMenu/ReportActionContextMenu.ts b/src/pages/inbox/report/ContextMenu/ReportActionContextMenu.ts index a4457ccfc46a..79f8be732205 100644 --- a/src/pages/inbox/report/ContextMenu/ReportActionContextMenu.ts +++ b/src/pages/inbox/report/ContextMenu/ReportActionContextMenu.ts @@ -30,6 +30,7 @@ type ShowContextMenuParams = { reportAction?: { reportActionID?: string; draftMessage?: string; + isThreadReportParentAction?: boolean; }; callbacks?: { onShow?: () => void; diff --git a/src/pages/inbox/report/PureReportActionItem.tsx b/src/pages/inbox/report/PureReportActionItem.tsx index 81fb902296d9..007fc77d67e4 100644 --- a/src/pages/inbox/report/PureReportActionItem.tsx +++ b/src/pages/inbox/report/PureReportActionItem.tsx @@ -552,6 +552,7 @@ function PureReportActionItem({ reportAction: { reportActionID: action.reportActionID, draftMessage, + isThreadReportParentAction, }, callbacks: { onShow: toggleContextMenuFromActiveReportAction, @@ -573,6 +574,7 @@ function PureReportActionItem({ disabledActions, isArchivedRoom, handleShowContextMenu, + isThreadReportParentAction, ], ); @@ -1139,6 +1141,7 @@ function PureReportActionItem({ displayAsGroup={displayAsGroup} disabledActions={disabledActions} isVisible={hovered && draftMessage === undefined && !hasErrors} + isThreadReportParentAction={isThreadReportParentAction} draftMessage={draftMessage} checkIfContextMenuActive={toggleContextMenuFromActiveReportAction} setIsEmojiPickerActive={setIsEmojiPickerActive}