diff --git a/src/components/ArchivedReportFooter.tsx b/src/components/ArchivedReportFooter.tsx index 260171e580b8..ff472f330841 100644 --- a/src/components/ArchivedReportFooter.tsx +++ b/src/components/ArchivedReportFooter.tsx @@ -4,7 +4,6 @@ import React from 'react'; import useLocalize from '@hooks/useLocalize'; import useOnyx from '@hooks/useOnyx'; import useThemeStyles from '@hooks/useThemeStyles'; -import {getCurrentUserAccountID} from '@libs/actions/Report'; import {getDisplayNameOrDefault} from '@libs/PersonalDetailsUtils'; import {getOriginalMessage, isClosedAction} from '@libs/ReportActionsUtils'; import {getPolicyName} from '@libs/ReportUtils'; @@ -17,9 +16,11 @@ import Banner from './Banner'; type ArchivedReportFooterProps = { /** The archived report */ report: Report; + /** Current user's account id */ + currentUserAccountID: number; }; -function ArchivedReportFooter({report}: ArchivedReportFooterProps) { +function ArchivedReportFooter({report, currentUserAccountID}: ArchivedReportFooterProps) { const styles = useThemeStyles(); const {translate} = useLocalize(); @@ -57,7 +58,7 @@ function ArchivedReportFooter({report}: ArchivedReportFooterProps) { displayName: `${displayName}`, oldDisplayName: `${oldDisplayName}`, policyName: `${policyName}`, - shouldUseYou: actorPersonalDetails?.accountID === getCurrentUserAccountID(), + shouldUseYou: actorPersonalDetails?.accountID === currentUserAccountID, }) : translate(`reportArchiveReasons.${archiveReason}`); diff --git a/src/components/PromotedActionsBar.tsx b/src/components/PromotedActionsBar.tsx index 5baf40ffb556..f077ffabc586 100644 --- a/src/components/PromotedActionsBar.tsx +++ b/src/components/PromotedActionsBar.tsx @@ -19,12 +19,14 @@ type PromotedAction = { key: string; } & ThreeDotsMenuItem; -type BasePromotedActions = typeof CONST.PROMOTED_ACTIONS.PIN | typeof CONST.PROMOTED_ACTIONS.JOIN; +type BasePromotedActions = typeof CONST.PROMOTED_ACTIONS.PIN; type PromotedActionsType = Record PromotedAction> & { [CONST.PROMOTED_ACTIONS.SHARE]: (report: OnyxReport, backTo?: string) => PromotedAction; } & { - [CONST.PROMOTED_ACTIONS.MESSAGE]: (params: {reportID?: string; accountID?: number; login?: string}) => PromotedAction; + [CONST.PROMOTED_ACTIONS.MESSAGE]: (params: {reportID?: string; accountID?: number; login?: string; currentUserAccountID: number}) => PromotedAction; +} & { + [CONST.PROMOTED_ACTIONS.JOIN]: (report: OnyxReport, currentUserAccountID: number) => PromotedAction; }; type PromotedActionsBarProps = { @@ -44,16 +46,16 @@ const PromotedActions = { key: CONST.PROMOTED_ACTIONS.SHARE, ...getShareMenuItem(report, backTo), }), - join: (report) => ({ + join: (report, currentUserAccountID) => ({ key: CONST.PROMOTED_ACTIONS.JOIN, icon: 'ChatBubbles', translationKey: 'common.join', onSelected: callFunctionIfActionIsAllowed(() => { Navigation.dismissModal(); - joinRoom(report); + joinRoom(report, currentUserAccountID); }), }), - message: ({reportID, accountID, login}) => ({ + message: ({reportID, accountID, login, currentUserAccountID}) => ({ key: CONST.PROMOTED_ACTIONS.MESSAGE, icon: 'CommentBubbles', translationKey: 'common.message', @@ -69,7 +71,7 @@ const PromotedActions = { return; } if (accountID) { - navigateToAndOpenReportWithAccountIDs([accountID]); + navigateToAndOpenReportWithAccountIDs([accountID], currentUserAccountID); } }, }), diff --git a/src/components/RoomHeaderAvatars.tsx b/src/components/RoomHeaderAvatars.tsx index a56a4f7f5a60..dde60ec66b70 100644 --- a/src/components/RoomHeaderAvatars.tsx +++ b/src/components/RoomHeaderAvatars.tsx @@ -4,7 +4,7 @@ import type {OnyxEntry} from 'react-native-onyx'; import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset'; import useStyleUtils from '@hooks/useStyleUtils'; import useThemeStyles from '@hooks/useThemeStyles'; -import {clearAvatarErrors, getCurrentUserAccountID, updatePolicyRoomAvatar} from '@libs/actions/Report'; +import {clearAvatarErrors, updatePolicyRoomAvatar} from '@libs/actions/Report'; import Navigation from '@libs/Navigation/Navigation'; import {isUserCreatedPolicyRoom} from '@libs/ReportUtils'; import {isDefaultAvatar} from '@libs/UserAvatarUtils'; @@ -22,9 +22,10 @@ type RoomHeaderAvatarsProps = { report: Report; policy: OnyxEntry; participants: number[]; + currentUserAccountID: number; }; -function RoomHeaderAvatars({icons, report, policy, participants}: RoomHeaderAvatarsProps) { +function RoomHeaderAvatars({icons, report, policy, participants, currentUserAccountID}: RoomHeaderAvatarsProps) { const navigateToAvatarPage = (icon: Icon) => { if (icon.type === CONST.ICON_TYPE_WORKSPACE && icon.id) { Navigation.navigate(ROUTES.REPORT_AVATAR.getRoute(report?.reportID, icon.id.toString())); @@ -39,7 +40,6 @@ function RoomHeaderAvatars({icons, report, policy, participants}: RoomHeaderAvat const expensifyIcons = useMemoizedLazyExpensifyIcons(['Camera', 'FallbackAvatar', 'ImageCropSquareMask']); const styles = useThemeStyles(); const StyleUtils = useStyleUtils(); - const currentUserAccountID = getCurrentUserAccountID(); const canEditRoomAvatar = isUserCreatedPolicyRoom(report) && participants.includes(currentUserAccountID) && !!policy && policy.role !== CONST.POLICY.ROLE.AUDITOR; if (!icons.length) { @@ -62,8 +62,8 @@ function RoomHeaderAvatars({icons, report, policy, participants}: RoomHeaderAvat size={CONST.AVATAR_SIZE.X_LARGE} avatarStyle={[styles.avatarXLarge, styles.alignSelfCenter]} onViewPhotoPress={() => Navigation.navigate(ROUTES.REPORT_AVATAR.getRoute(report.reportID))} - onImageRemoved={() => updatePolicyRoomAvatar(report.reportID)} - onImageSelected={(file) => updatePolicyRoomAvatar(report.reportID, file)} + onImageRemoved={() => updatePolicyRoomAvatar(report.reportID, currentUserAccountID)} + onImageSelected={(file) => updatePolicyRoomAvatar(report.reportID, currentUserAccountID, file)} editIcon={expensifyIcons.Camera} editIconStyle={styles.smallEditIconAccount} pendingAction={report.pendingFields?.avatar} diff --git a/src/components/Share/ShareTabParticipantsSelector.tsx b/src/components/Share/ShareTabParticipantsSelector.tsx index ddea87c8d2e4..c1727f0f269a 100644 --- a/src/components/Share/ShareTabParticipantsSelector.tsx +++ b/src/components/Share/ShareTabParticipantsSelector.tsx @@ -1,5 +1,6 @@ import type {Ref} from 'react'; import React from 'react'; +import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; import {clearMoneyRequest} from '@libs/actions/IOU'; import {saveUnknownUserDetails} from '@libs/actions/Share'; import Navigation from '@libs/Navigation/Navigation'; @@ -18,6 +19,7 @@ type InputFocusRef = { }; function ShareTabParticipantsSelectorComponent({detailsPageRouteObject, ref}: ShareTabParticipantsSelectorProps) { + const {accountID: currentUserAccountID} = useCurrentUserPersonalDetails(); return ( { diff --git a/src/libs/actions/Report.ts b/src/libs/actions/Report.ts index 469cf74c80da..4aabb6636cde 100644 --- a/src/libs/actions/Report.ts +++ b/src/libs/actions/Report.ts @@ -408,7 +408,7 @@ function getNormalizedStatus(typingStatus: UserIsTypingEvent | UserIsLeavingRoom } /** Initialize our pusher subscriptions to listen for someone typing in a report. */ -function subscribeToReportTypingEvents(reportID: string) { +function subscribeToReportTypingEvents(reportID: string, currentUserAccountID: number) { if (!reportID) { return; } @@ -429,7 +429,7 @@ function subscribeToReportTypingEvents(reportID: string) { } // Don't show the typing indicator if the user is typing on another platform - if (Number(accountIDOrLogin) === deprecatedCurrentUserAccountID) { + if (Number(accountIDOrLogin) === currentUserAccountID) { return; } @@ -458,7 +458,7 @@ function subscribeToReportTypingEvents(reportID: string) { } /** Initialize our pusher subscriptions to listen for someone leaving a room. */ -function subscribeToReportLeavingEvents(reportID: string | undefined) { +function subscribeToReportLeavingEvents(reportID: string | undefined, currentUserAccountID: number) { if (!reportID) { return; } @@ -478,7 +478,7 @@ function subscribeToReportLeavingEvents(reportID: string | undefined) { return; } - if (Number(accountIDOrLogin) !== deprecatedCurrentUserAccountID) { + if (Number(accountIDOrLogin) !== currentUserAccountID) { return; } @@ -889,7 +889,7 @@ function updateGroupChatAvatar(reportID: string, file?: File | CustomRNImageMani /** * Updates the avatar for a policy room. */ -function updatePolicyRoomAvatar(reportID: string, file?: File | CustomRNImageManipulatorResult) { +function updatePolicyRoomAvatar(reportID: string, currentUserAccountID: number, file?: File | CustomRNImageManipulatorResult) { const avatarURL = file?.uri ?? ''; const {optimisticData, successData, failureData} = buildUpdateReportAvatarOnyxData(reportID, file); @@ -905,7 +905,7 @@ function updatePolicyRoomAvatar(reportID: string, file?: File | CustomRNImageMan onyxMethod: Onyx.METHOD.MERGE, key: `${ONYXKEYS.COLLECTION.REPORT}${reportID}`, value: { - lastActorAccountID: deprecatedCurrentUserAccountID, + lastActorAccountID: currentUserAccountID, lastVisibleActionCreated: optimisticAction.created, lastMessageText: (optimisticAction.message as Message[]).at(0)?.text, }, @@ -1408,9 +1408,9 @@ function prepareOnyxDataForCleanUpOptimisticParticipants( * This will return an optimistic report object for a given user we want to create a chat with without saving it, when the only thing we know about recipient is his accountID. * * @param accountID accountID of the user that the optimistic chat report is created with. */ -function getOptimisticChatReport(accountID: number): OptimisticChatReport { +function getOptimisticChatReport(accountID: number, currentUserAccountID: number): OptimisticChatReport { return buildOptimisticChatReport({ - participantList: [accountID, deprecatedCurrentUserAccountID], + participantList: [accountID, currentUserAccountID], notificationPreference: CONST.REPORT.NOTIFICATION_PREFERENCE.ALWAYS, }); } @@ -1537,12 +1537,12 @@ function navigateToAndOpenReport( * * @param participantAccountIDs of user logins to start a chat report with. */ -function navigateToAndOpenReportWithAccountIDs(participantAccountIDs: number[]) { +function navigateToAndOpenReportWithAccountIDs(participantAccountIDs: number[], currentUserAccountID: number) { let newChat: OptimisticChatReport | undefined; - const chat = getChatByParticipants([...participantAccountIDs, deprecatedCurrentUserAccountID]); + const chat = getChatByParticipants([...participantAccountIDs, currentUserAccountID]); if (!chat) { newChat = buildOptimisticChatReport({ - participantList: [...participantAccountIDs, deprecatedCurrentUserAccountID], + participantList: [...participantAccountIDs, currentUserAccountID], }); // We want to pass newChat here because if anything is passed in that param (even an existing chat), we will try to create a chat on the server openReport(newChat?.reportID, '', [], newChat, '0', false, participantAccountIDs); @@ -1824,7 +1824,7 @@ function markAllMessagesAsRead(archivedReportsIdSet: ArchivedReportsIDSet) { /** * Sets the last read time on a report */ -function markCommentAsUnread(reportID: string | undefined, reportAction: ReportAction) { +function markCommentAsUnread(reportID: string | undefined, reportAction: ReportAction, currentUserAccountID: number) { if (!reportID) { Log.warn('7339cd6c-3263-4f89-98e5-730f0be15784 Invalid report passed to MarkCommentAsUnread. Not calling the API because it wil fail.'); return; @@ -1836,7 +1836,7 @@ function markCommentAsUnread(reportID: string | undefined, reportAction: ReportA const latestReportActionFromOtherUsers = Object.values(reportActions ?? {}).reduce((latest: ReportAction | null, current: ReportAction) => { if ( !ReportActionsUtils.isDeletedAction(current) && - current.actorAccountID !== deprecatedCurrentUserAccountID && + current.actorAccountID !== currentUserAccountID && (!latest || current.created > latest.created) && // Whisper action doesn't affect lastVisibleActionCreated, so skip whisper action except actionable mention whisper (!ReportActionsUtils.isWhisperAction(current) || current.actionName === CONST.REPORT.ACTIONS.TYPE.ACTIONABLE_MENTION_WHISPER) @@ -1921,19 +1921,19 @@ function saveReportDraftComment(reportID: string, comment: string | null, callba } /** Broadcasts whether or not a user is typing on a report over the report's private pusher channel. */ -function broadcastUserIsTyping(reportID: string) { +function broadcastUserIsTyping(reportID: string, currentUserAccountID: number) { const privateReportChannelName = getReportChannelName(reportID); const typingStatus: UserIsTypingEvent = { - [deprecatedCurrentUserAccountID]: true, + [currentUserAccountID]: true, }; Pusher.sendEvent(privateReportChannelName, Pusher.TYPE.USER_IS_TYPING, typingStatus); } /** Broadcasts to the report's private pusher channel whether a user is leaving a report */ -function broadcastUserIsLeavingRoom(reportID: string) { +function broadcastUserIsLeavingRoom(reportID: string, currentUserAccountID: number) { const privateReportChannelName = getReportChannelName(reportID); const leavingStatus: UserIsLeavingRoomEvent = { - [deprecatedCurrentUserAccountID]: true, + [currentUserAccountID]: true, }; Pusher.sendEvent(privateReportChannelName, Pusher.TYPE.USER_IS_LEAVING_ROOM, leavingStatus); } @@ -2356,6 +2356,7 @@ function updateNotificationPreference( reportID: string, previousValue: NotificationPreference | undefined, newValue: NotificationPreference, + currentUserAccountID: number, parentReportID?: string, parentReportActionID?: string, ) { @@ -2370,7 +2371,7 @@ function updateNotificationPreference( key: `${ONYXKEYS.COLLECTION.REPORT}${reportID}`, value: { participants: { - [deprecatedCurrentUserAccountID]: { + [currentUserAccountID]: { notificationPreference: newValue, }, }, @@ -2384,7 +2385,7 @@ function updateNotificationPreference( key: `${ONYXKEYS.COLLECTION.REPORT}${reportID}`, value: { participants: { - [deprecatedCurrentUserAccountID]: { + [currentUserAccountID]: { notificationPreference: previousValue, }, }, @@ -2446,6 +2447,7 @@ function updateRoomVisibility(reportID: string, previousValue: RoomVisibility | */ function toggleSubscribeToChildReport( childReportID: string | undefined, + currentUserAccountID: number, parentReportAction: Partial = {}, parentReportID?: string, prevNotificationPreference?: NotificationPreference, @@ -2454,12 +2456,12 @@ function toggleSubscribeToChildReport( openReport(childReportID); const parentReportActionID = parentReportAction?.reportActionID; if (!prevNotificationPreference || isHiddenForCurrentUser(prevNotificationPreference)) { - updateNotificationPreference(childReportID, prevNotificationPreference, CONST.REPORT.NOTIFICATION_PREFERENCE.ALWAYS, parentReportID, parentReportActionID); + updateNotificationPreference(childReportID, prevNotificationPreference, CONST.REPORT.NOTIFICATION_PREFERENCE.ALWAYS, currentUserAccountID, parentReportID, parentReportActionID); } else { - updateNotificationPreference(childReportID, prevNotificationPreference, CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN, parentReportID, parentReportActionID); + updateNotificationPreference(childReportID, prevNotificationPreference, CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN, currentUserAccountID, parentReportID, parentReportActionID); } } else { - const participantAccountIDs = [...new Set([deprecatedCurrentUserAccountID, Number(parentReportAction?.actorAccountID)])]; + const participantAccountIDs = [...new Set([currentUserAccountID, Number(parentReportAction?.actorAccountID)])]; const parentReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${parentReportID}`]; const newChat = buildOptimisticChatReport({ participantList: participantAccountIDs, @@ -2475,7 +2477,7 @@ function toggleSubscribeToChildReport( const participantLogins = PersonalDetailsUtils.getLoginsByAccountIDs(participantAccountIDs); openReport(newChat.reportID, '', participantLogins, newChat, parentReportAction.reportActionID); const notificationPreference = isHiddenForCurrentUser(prevNotificationPreference) ? CONST.REPORT.NOTIFICATION_PREFERENCE.ALWAYS : CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN; - updateNotificationPreference(newChat.reportID, prevNotificationPreference, notificationPreference, parentReportID, parentReportAction?.reportActionID); + updateNotificationPreference(newChat.reportID, prevNotificationPreference, notificationPreference, currentUserAccountID, parentReportID, parentReportAction?.reportActionID); } } @@ -2777,7 +2779,7 @@ function deleteReportField(reportID: string, reportField: PolicyReportField) { API.write(WRITE_COMMANDS.DELETE_REPORT_FIELD, parameters, {optimisticData, failureData, successData}); } -function updateDescription(reportID: string, currentDescription: string, newMarkdownValue: string) { +function updateDescription(reportID: string, currentDescription: string, newMarkdownValue: string, currentUserAccountID: number) { // No change needed if (Parser.htmlToMarkdown(currentDescription) === newMarkdownValue) { return; @@ -2794,7 +2796,7 @@ function updateDescription(reportID: string, currentDescription: string, newMark value: { description: parsedDescription, pendingFields: {description: CONST.RED_BRICK_ROAD_PENDING_ACTION.UPDATE}, - lastActorAccountID: deprecatedCurrentUserAccountID, + lastActorAccountID: currentUserAccountID, lastVisibleActionCreated: optimisticDescriptionUpdatedReportAction.created, lastMessageText: (optimisticDescriptionUpdatedReportAction?.message as Message[])?.at(0)?.text, }, @@ -3550,7 +3552,7 @@ function clearIOUError(reportID: string | undefined) { * Adds a reaction to the report action. * Uses the NEW FORMAT for "emojiReactions" */ -function addEmojiReaction(reportID: string, reportActionID: string, emoji: Emoji, skinTone: number) { +function addEmojiReaction(reportID: string, reportActionID: string, emoji: Emoji, skinTone: number, currentUserAccountID: number) { const createdAt = timezoneFormat(toZonedTime(new Date(), 'UTC'), CONST.DATE.FNS_DB_FORMAT_STRING); const optimisticData: Array> = [ { @@ -3561,7 +3563,7 @@ function addEmojiReaction(reportID: string, reportActionID: string, emoji: Emoji createdAt, pendingAction: CONST.RED_BRICK_ROAD_PENDING_ACTION.ADD, users: { - [deprecatedCurrentUserAccountID]: { + [currentUserAccountID]: { skinTones: { [skinTone]: createdAt, }, @@ -3611,7 +3613,7 @@ function addEmojiReaction(reportID: string, reportActionID: string, emoji: Emoji * Removes a reaction to the report action. * Uses the NEW FORMAT for "emojiReactions" */ -function removeEmojiReaction(reportID: string, reportActionID: string, emoji: Emoji) { +function removeEmojiReaction(reportID: string, reportActionID: string, emoji: Emoji, currentUserAccountID: number) { const optimisticData: Array> = [ { onyxMethod: Onyx.METHOD.MERGE, @@ -3619,7 +3621,7 @@ function removeEmojiReaction(reportID: string, reportActionID: string, emoji: Em value: { [emoji.name]: { users: { - [deprecatedCurrentUserAccountID]: null, + [currentUserAccountID]: null, }, }, }, @@ -3645,6 +3647,7 @@ function toggleEmojiReaction( reactionObject: Emoji, existingReactions: OnyxEntry, paramSkinTone: number, + currentUserAccountID: number, ignoreSkinToneOnCompare = false, ) { const originalReportID = getOriginalReportID(reportID, reportAction); @@ -3667,12 +3670,12 @@ function toggleEmojiReaction( // Only use skin tone if emoji supports it const skinTone = emoji.types === undefined ? CONST.EMOJI_DEFAULT_SKIN_TONE : paramSkinTone; - if (existingReactionObject && EmojiUtils.hasAccountIDEmojiReacted(deprecatedCurrentUserAccountID, existingReactionObject.users, ignoreSkinToneOnCompare ? undefined : skinTone)) { - removeEmojiReaction(originalReportID, reportAction.reportActionID, emoji); + if (existingReactionObject && EmojiUtils.hasAccountIDEmojiReacted(currentUserAccountID, existingReactionObject.users, ignoreSkinToneOnCompare ? undefined : skinTone)) { + removeEmojiReaction(originalReportID, reportAction.reportActionID, emoji, currentUserAccountID); return; } - addEmojiReaction(originalReportID, reportAction.reportActionID, emoji, skinTone); + addEmojiReaction(originalReportID, reportAction.reportActionID, emoji, skinTone, currentUserAccountID); } function doneCheckingPublicRoom() { @@ -3706,7 +3709,7 @@ function getMostRecentReportID(currentReport: OnyxEntry) { return lastAccessedReportID ?? conciergeReportID; } -function joinRoom(report: OnyxEntry) { +function joinRoom(report: OnyxEntry, currentUserAccountID: number) { if (!report) { return; } @@ -3714,12 +3717,13 @@ function joinRoom(report: OnyxEntry) { report.reportID, getReportNotificationPreference(report), getDefaultNotificationPreferenceForReport(report), + currentUserAccountID, report.parentReportID, report.parentReportActionID, ); } -function leaveGroupChat(reportID: string, shouldClearQuickAction: boolean) { +function leaveGroupChat(reportID: string, shouldClearQuickAction: boolean, currentUserAccountID: number) { const report = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`]; if (!report) { Log.warn('Attempting to leave Group Chat that does not existing locally'); @@ -3737,7 +3741,7 @@ function leaveGroupChat(reportID: string, shouldClearQuickAction: boolean) { stateNum: CONST.REPORT.STATE_NUM.APPROVED, statusNum: CONST.REPORT.STATUS_NUM.CLOSED, participants: { - [deprecatedCurrentUserAccountID]: { + [currentUserAccountID]: { notificationPreference: CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN, }, }, @@ -3776,7 +3780,7 @@ function leaveGroupChat(reportID: string, shouldClearQuickAction: boolean) { } /** Leave a report by setting the state to submitted and closed */ -function leaveRoom(reportID: string, isWorkspaceMemberLeavingWorkspaceRoom = false) { +function leaveRoom(reportID: string, currentUserAccountID: number, isWorkspaceMemberLeavingWorkspaceRoom = false) { const report = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${reportID}`]; if (!report) { @@ -3787,7 +3791,7 @@ function leaveRoom(reportID: string, isWorkspaceMemberLeavingWorkspaceRoom = fal // Pusher's leavingStatus should be sent earlier. // Place the broadcast before calling the LeaveRoom API to prevent a race condition // between Onyx report being null and Pusher's leavingStatus becoming true. - broadcastUserIsLeavingRoom(reportID); + broadcastUserIsLeavingRoom(reportID, currentUserAccountID); // If a workspace member is leaving a workspace room, they don't actually lose the room from Onyx. // Instead, their notification preference just gets set to "hidden". @@ -3800,7 +3804,7 @@ function leaveRoom(reportID: string, isWorkspaceMemberLeavingWorkspaceRoom = fal isWorkspaceMemberLeavingWorkspaceRoom || isChatThread ? { participants: { - [deprecatedCurrentUserAccountID]: { + [currentUserAccountID]: { notificationPreference: CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN, }, }, @@ -3810,7 +3814,7 @@ function leaveRoom(reportID: string, isWorkspaceMemberLeavingWorkspaceRoom = fal stateNum: CONST.REPORT.STATE_NUM.APPROVED, statusNum: CONST.REPORT.STATUS_NUM.CLOSED, participants: { - [deprecatedCurrentUserAccountID]: { + [currentUserAccountID]: { notificationPreference: CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN, }, }, @@ -3825,7 +3829,7 @@ function leaveRoom(reportID: string, isWorkspaceMemberLeavingWorkspaceRoom = fal key: `${ONYXKEYS.COLLECTION.REPORT}${reportID}`, value: { participants: { - [deprecatedCurrentUserAccountID]: { + [currentUserAccountID]: { notificationPreference: CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN, }, }, @@ -3865,7 +3869,7 @@ function leaveRoom(reportID: string, isWorkspaceMemberLeavingWorkspaceRoom = fal key: `${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${report.parentReportID}`, value: { [report.parentReportActionID]: { - childReportNotificationPreference: report?.participants?.[deprecatedCurrentUserAccountID]?.notificationPreference ?? getDefaultNotificationPreferenceForReport(report), + childReportNotificationPreference: report?.participants?.[currentUserAccountID]?.notificationPreference ?? getDefaultNotificationPreferenceForReport(report), }, }, }); @@ -5752,7 +5756,7 @@ function navigateToTrainingModal(isChangePolicyTrainingModalDismissed: boolean, function buildOptimisticChangePolicyData( report: Report, policy: Policy, - accountID: number, + currentUserAccountID: number, email: string, hasViolationsParam: boolean, isASAPSubmitBetaEnabled: boolean, @@ -5837,7 +5841,7 @@ function buildOptimisticChangePolicyData( report: {...report, policyID: policy.id}, predictedNextStatus: newStatusNum, policy, - currentUserAccountIDParam: accountID, + currentUserAccountIDParam: currentUserAccountID, currentUserEmailParam: email, hasViolations: hasViolationsParam, isASAPSubmitBetaEnabled, @@ -5846,7 +5850,7 @@ function buildOptimisticChangePolicyData( report: {...report, policyID: policy.id}, predictedNextStatus: newStatusNum, policy, - currentUserAccountIDParam: accountID, + currentUserAccountIDParam: currentUserAccountID, currentUserEmailParam: email, hasViolations: hasViolationsParam, isASAPSubmitBetaEnabled, @@ -5901,7 +5905,7 @@ function buildOptimisticChangePolicyData( if (newStatusNum === CONST.REPORT.STATUS_NUM.OPEN) { shouldSetOutstandingChildRequest = isCurrentUserSubmitter(report); } else if (isProcessingReport(report)) { - shouldSetOutstandingChildRequest = report.managerID === deprecatedCurrentUserAccountID; + shouldSetOutstandingChildRequest = report.managerID === currentUserAccountID; } } @@ -6246,7 +6250,7 @@ function changeReportPolicy( function changeReportPolicyAndInviteSubmitter( report: Report, policy: Policy, - accountID: number, + currentUserAccountID: number, email: string, hasViolationsParam: boolean, isChangePolicyTrainingModalDismissed: boolean, @@ -6289,7 +6293,7 @@ function changeReportPolicyAndInviteSubmitter( } = buildOptimisticChangePolicyData( report, policy, - accountID, + currentUserAccountID, email, hasViolationsParam, isASAPSubmitBetaEnabled, diff --git a/src/pages/ProfilePage.tsx b/src/pages/ProfilePage.tsx index 3680549deb34..dac2ba12e39b 100755 --- a/src/pages/ProfilePage.tsx +++ b/src/pages/ProfilePage.tsx @@ -16,6 +16,7 @@ import PromotedActionsBar, {PromotedActions} from '@components/PromotedActionsBa import ScreenWrapper from '@components/ScreenWrapper'; import ScrollView from '@components/ScrollView'; import Text from '@components/Text'; +import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset'; import useLocalize from '@hooks/useLocalize'; import useOnyx from '@hooks/useOnyx'; @@ -70,22 +71,21 @@ function ProfilePage({route}: ProfilePageProps) { const [reports] = useOnyx(ONYXKEYS.COLLECTION.REPORT, {selector: reportsSelector, canBeMissing: true}); const [personalDetails] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_LIST, {canBeMissing: true}); const [personalDetailsMetadata] = useOnyx(ONYXKEYS.PERSONAL_DETAILS_METADATA, {canBeMissing: true}); - const [session] = useOnyx(ONYXKEYS.SESSION, {canBeMissing: false}); + const {accountID: currentUserAccountID} = useCurrentUserPersonalDetails(); const [account] = useOnyx(ONYXKEYS.ACCOUNT, {canBeMissing: true}); const [isDebugModeEnabled = false] = useOnyx(ONYXKEYS.IS_DEBUG_MODE_ENABLED, {canBeMissing: true}); const guideCalendarLink = account?.guideDetails?.calendarLink ?? ''; const expensifyIcons = useMemoizedLazyExpensifyIcons(['Bug', 'Pencil', 'Phone']); const accountID = Number(route.params?.accountID ?? CONST.DEFAULT_NUMBER_ID); - const isCurrentUser = session?.accountID === accountID; + const isCurrentUser = currentUserAccountID === accountID; const reportKey = useMemo(() => { - const reportID = isCurrentUser ? findSelfDMReportID() : getChatByParticipants(session?.accountID ? [accountID, session.accountID] : [], reports)?.reportID; + const reportID = isCurrentUser ? findSelfDMReportID() : getChatByParticipants(currentUserAccountID ? [accountID, currentUserAccountID] : [], reports)?.reportID; if (isAnonymousUserSession() || !reportID) { return `${ONYXKEYS.COLLECTION.REPORT}0` as const; } return `${ONYXKEYS.COLLECTION.REPORT}${reportID}` as const; - }, [accountID, isCurrentUser, reports, session?.accountID]); - + }, [accountID, isCurrentUser, reports, currentUserAccountID]); const [report] = useOnyx(reportKey, {canBeMissing: true}); const styles = useThemeStyles(); @@ -168,10 +168,10 @@ function ProfilePage({route}: ProfilePageProps) { // If it's a self DM, we only want to show the Message button if the self DM report exists because we don't want to optimistically create a report for self DM if ((!isCurrentUser || report) && !isAnonymousUserSession()) { - result.push(PromotedActions.message({reportID: report?.reportID, accountID, login: loginParams})); + result.push(PromotedActions.message({reportID: report?.reportID, accountID, login: loginParams, currentUserAccountID})); } return result; - }, [accountID, isCurrentUser, loginParams, report]); + }, [accountID, isCurrentUser, loginParams, report, currentUserAccountID]); return ( @@ -271,7 +271,7 @@ function ProfilePage({route}: ProfilePageProps) { title={`${translate('privateNotes.title')}`} titleStyle={styles.flex1} icon={expensifyIcons.Pencil} - onPress={() => navigateToPrivateNotes(report, session?.accountID ?? CONST.DEFAULT_NUMBER_ID, navigateBackTo)} + onPress={() => navigateToPrivateNotes(report, currentUserAccountID, navigateBackTo)} wrapperStyle={styles.breakAll} shouldShowRightIcon brickRoadIndicator={hasErrorInPrivateNotes(report) ? CONST.BRICK_ROAD_INDICATOR_STATUS.ERROR : undefined} diff --git a/src/pages/ReportDetailsPage.tsx b/src/pages/ReportDetailsPage.tsx index ce3ab6b0db79..7eb383470ade 100644 --- a/src/pages/ReportDetailsPage.tsx +++ b/src/pages/ReportDetailsPage.tsx @@ -328,13 +328,13 @@ function ReportDetailsPage({policy, report, route, reportMetadata}: ReportDetail Navigation.dismissModal(); Navigation.isNavigationReady().then(() => { if (isRootGroupChat) { - leaveGroupChat(report.reportID, quickAction?.chatReportID?.toString() === report.reportID); + leaveGroupChat(report.reportID, quickAction?.chatReportID?.toString() === report.reportID, currentUserPersonalDetails.accountID); return; } const isWorkspaceMemberLeavingWorkspaceRoom = isWorkspaceMemberLeavingWorkspaceRoomUtil(report, isPolicyEmployee, isPolicyAdmin); - leaveRoom(report.reportID, isWorkspaceMemberLeavingWorkspaceRoom); + leaveRoom(report.reportID, currentUserPersonalDetails.accountID, isWorkspaceMemberLeavingWorkspaceRoom); }); - }, [isRootGroupChat, isPolicyEmployee, isPolicyAdmin, quickAction?.chatReportID, report]); + }, [isRootGroupChat, isPolicyEmployee, isPolicyAdmin, quickAction?.chatReportID, report, currentUserPersonalDetails.accountID]); const shouldShowLeaveButton = canLeaveChat(report, policy, !!reportNameValuePairs?.private_isArchived); const shouldShowGoToWorkspace = shouldShowPolicy(policy, false, currentUserPersonalDetails?.email) && !policy?.isJoinRequestPending; @@ -616,6 +616,7 @@ function ReportDetailsPage({policy, report, route, reportMetadata}: ReportDetail report={report} policy={policy} participants={participants} + currentUserAccountID={currentUserPersonalDetails.accountID} /> ); @@ -671,6 +672,7 @@ function ReportDetailsPage({policy, report, route, reportMetadata}: ReportDetail participants, moneyRequestReport?.reportID, expensifyIcons.Camera, + currentUserPersonalDetails?.accountID, ]); const canJoin = canJoinChat(report, parentReportAction, policy, parentReport, !!reportNameValuePairs?.private_isArchived); @@ -679,7 +681,7 @@ function ReportDetailsPage({policy, report, route, reportMetadata}: ReportDetail const result: PromotedAction[] = []; if (canJoin) { - result.push(PromotedActions.join(report)); + result.push(PromotedActions.join(report, currentUserPersonalDetails.accountID)); } if (report) { @@ -689,7 +691,7 @@ function ReportDetailsPage({policy, report, route, reportMetadata}: ReportDetail result.push(PromotedActions.share(report, backTo)); return result; - }, [canJoin, report, backTo]); + }, [canJoin, report, backTo, currentUserPersonalDetails.accountID]); const nameSectionExpenseIOU = ( diff --git a/src/pages/RoomDescriptionPage.tsx b/src/pages/RoomDescriptionPage.tsx index 021142d24f9e..94a03028d3f1 100644 --- a/src/pages/RoomDescriptionPage.tsx +++ b/src/pages/RoomDescriptionPage.tsx @@ -12,6 +12,7 @@ import ScrollView from '@components/ScrollView'; import Text from '@components/Text'; import TextInput from '@components/TextInput'; import type {BaseTextInputRef} from '@components/TextInput/BaseTextInput/types'; +import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; import useLocalize from '@hooks/useLocalize'; import useReportIsArchived from '@hooks/useReportIsArchived'; import useThemeStyles from '@hooks/useThemeStyles'; @@ -48,7 +49,7 @@ function RoomDescriptionPage({report, policy}: RoomDescriptionPageProps) { const focusTimeoutRef = useRef | null>(null); const {translate} = useLocalize(); const reportIsArchived = useReportIsArchived(report?.reportID); - + const {accountID: currentUserAccountID} = useCurrentUserPersonalDetails(); const handleReportDescriptionChange = useCallback((value: string) => { setDescription(value); }, []); @@ -61,9 +62,9 @@ function RoomDescriptionPage({report, policy}: RoomDescriptionPageProps) { const previousValue = report?.description ?? ''; const newValue = description.trim(); - updateDescription(report.reportID, previousValue, newValue); + updateDescription(report.reportID, previousValue, newValue, currentUserAccountID); goBack(); - }, [report.reportID, report.description, description, goBack]); + }, [report.reportID, report.description, description, goBack, currentUserAccountID]); const validate = useCallback( (values: FormOnyxValues): Errors => { diff --git a/src/pages/Share/ShareTab.tsx b/src/pages/Share/ShareTab.tsx index 9237a15e7e74..1eda39749bf9 100644 --- a/src/pages/Share/ShareTab.tsx +++ b/src/pages/Share/ShareTab.tsx @@ -6,6 +6,7 @@ import SelectionList from '@components/SelectionList'; import InviteMemberListItem from '@components/SelectionList/ListItem/InviteMemberListItem'; import type {ListItem, SelectionListHandle} from '@components/SelectionList/types'; import Text from '@components/Text'; +import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; import useDebouncedState from '@hooks/useDebouncedState'; import useLocalize from '@hooks/useLocalize'; import useNetwork from '@hooks/useNetwork'; @@ -50,7 +51,7 @@ function ShareTab({ref}: ShareTabProps) { const [loginList] = useOnyx(ONYXKEYS.LOGIN_LIST, {canBeMissing: true}); const [draftComments] = useOnyx(ONYXKEYS.COLLECTION.REPORT_DRAFT_COMMENT, {canBeMissing: true}); const [nvpDismissedProductTraining] = useOnyx(ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING, {canBeMissing: true}); - + const {accountID: currentUserAccountID} = useCurrentUserPersonalDetails(); useImperativeHandle(ref, () => ({ focus: selectionListRef.current?.focusTextInput, })); @@ -121,7 +122,7 @@ function ShareTab({ref}: ShareTabProps) { const accountID = item?.accountID; if (accountID && !reportID) { saveUnknownUserDetails(item); - const optimisticReport = getOptimisticChatReport(accountID); + const optimisticReport = getOptimisticChatReport(accountID, currentUserAccountID); reportID = optimisticReport.reportID; saveReportDraft(reportID, optimisticReport).then(() => { diff --git a/src/pages/home/HeaderView.tsx b/src/pages/home/HeaderView.tsx index 21f7af25083e..699d249accd4 100644 --- a/src/pages/home/HeaderView.tsx +++ b/src/pages/home/HeaderView.tsx @@ -21,6 +21,7 @@ import SidePanelButton from '@components/SidePanel/SidePanelButton'; import TaskHeaderActionButton from '@components/TaskHeaderActionButton'; import Text from '@components/Text'; import Tooltip from '@components/Tooltip'; +import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; import useHasTeam2025Pricing from '@hooks/useHasTeam2025Pricing'; import {useMemoizedLazyExpensifyIcons} from '@hooks/useLazyAsset'; import useLoadingBarVisibility from '@hooks/useLoadingBarVisibility'; @@ -142,6 +143,7 @@ function HeaderView({report, parentReportAction, onNavigationMenuButtonClicked, const isParentOneTransactionThread = isOneTransactionThread(parentReport, grandParentReport, grandParentReportActions?.[`${parentReport?.parentReportActionID}`]); const parentNavigationReport = isParentOneTransactionThread ? parentReport : reportHeaderData; const isReportHeaderDataArchived = useReportIsArchived(reportHeaderData?.reportID); + const {accountID: currentUserAccountID} = useCurrentUserPersonalDetails(); // Use sorted display names for the title for group chats on native small screen widths // eslint-disable-next-line @typescript-eslint/no-deprecated const title = getReportName(reportHeaderData, policy, parentReportAction, personalDetails, invoiceReceiverPolicy, undefined, undefined, isReportHeaderDataArchived); @@ -182,7 +184,7 @@ function HeaderView({report, parentReportAction, onNavigationMenuButtonClicked, !isChatThread && introSelected?.companySize !== CONST.ONBOARDING_COMPANY_SIZE.MICRO; - const join = callFunctionIfActionIsAllowed(() => joinRoom(report)); + const join = callFunctionIfActionIsAllowed(() => joinRoom(report, currentUserAccountID)); const canJoin = canJoinChat(report, parentReportAction, policy, parentReport, isReportArchived); diff --git a/src/pages/home/ReportScreen.tsx b/src/pages/home/ReportScreen.tsx index 99e14c82338a..e6a752a84ed4 100644 --- a/src/pages/home/ReportScreen.tsx +++ b/src/pages/home/ReportScreen.tsx @@ -807,7 +807,7 @@ function ReportScreen({route, navigation, isInSidePanel = false}: ReportScreenPr if (!didSubscribeToReportLeavingEvents.current && didCreateReportSuccessfully) { // eslint-disable-next-line @typescript-eslint/no-deprecated interactionTask = InteractionManager.runAfterInteractions(() => { - subscribeToReportLeavingEvents(reportIDFromRoute); + subscribeToReportLeavingEvents(reportIDFromRoute, currentUserAccountID); didSubscribeToReportLeavingEvents.current = true; }); } @@ -817,7 +817,7 @@ function ReportScreen({route, navigation, isInSidePanel = false}: ReportScreenPr } interactionTask.cancel(); }; - }, [report?.reportID, didSubscribeToReportLeavingEvents, reportIDFromRoute, report?.pendingFields]); + }, [report?.reportID, didSubscribeToReportLeavingEvents, reportIDFromRoute, report?.pendingFields, currentUserAccountID]); const actionListValue = useMemo((): ActionListContextType => ({flatListRef, scrollPosition, setScrollPosition}), [flatListRef, scrollPosition, setScrollPosition]); diff --git a/src/pages/home/report/ContextMenu/BaseReportActionContextMenu.tsx b/src/pages/home/report/ContextMenu/BaseReportActionContextMenu.tsx index dbfa0b65753e..b0c80ac45b24 100755 --- a/src/pages/home/report/ContextMenu/BaseReportActionContextMenu.tsx +++ b/src/pages/home/report/ContextMenu/BaseReportActionContextMenu.tsx @@ -10,6 +10,7 @@ import type {ContextMenuItemHandle} from '@components/ContextMenuItem'; import ContextMenuItem from '@components/ContextMenuItem'; import FocusTrapForModal from '@components/FocusTrap/FocusTrapForModal'; import useArrowKeyFocusManager from '@hooks/useArrowKeyFocusManager'; +import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; import useEnvironment from '@hooks/useEnvironment'; import useGetExpensifyCardFromReportAction from '@hooks/useGetExpensifyCardFromReportAction'; import useKeyboardShortcut from '@hooks/useKeyboardShortcut'; @@ -199,7 +200,7 @@ function BaseReportActionContextMenu({ const [childChatReport] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT}${childReport?.chatReportID}`, {canBeMissing: true}); const parentReportAction = getReportAction(childReport?.parentReportID, childReport?.parentReportActionID); const {reportActions: paginatedReportActions} = usePaginatedReportActions(childReport?.reportID); - + const {accountID: currentUserAccountID} = useCurrentUserPersonalDetails(); const transactionThreadReportID = useMemo( () => getOneTransactionThreadReportID(childReport, childChatReport, paginatedReportActions ?? [], isOffline), [paginatedReportActions, isOffline, childReport, childChatReport], @@ -406,6 +407,7 @@ function BaseReportActionContextMenu({ policyTags, translate, harvestReport, + currentUserAccountID, }; if ('renderContent' in contextAction) { diff --git a/src/pages/home/report/ContextMenu/ContextMenuActions.tsx b/src/pages/home/report/ContextMenu/ContextMenuActions.tsx index 1ab0a98c3093..5f1d39b4dd44 100644 --- a/src/pages/home/report/ContextMenu/ContextMenuActions.tsx +++ b/src/pages/home/report/ContextMenu/ContextMenuActions.tsx @@ -212,6 +212,7 @@ type ContextMenuActionPayload = { reportAction: ReportAction; transaction?: OnyxEntry; reportID: string | undefined; + currentUserAccountID: number; report: OnyxEntry; draftMessage: string; selection: string; @@ -298,7 +299,7 @@ const ContextMenuActions: ContextMenuAction[] = [ const isDynamicWorkflowRoutedAction = isActionOfType(reportAction, CONST.REPORT.ACTIONS.TYPE.DYNAMIC_EXTERNAL_WORKFLOW_ROUTED); return type === CONST.CONTEXT_MENU_TYPES.REPORT_ACTION && !!reportAction && 'message' in reportAction && !isMessageDeleted(reportAction) && !isDynamicWorkflowRoutedAction; }, - renderContent: (closePopover, {reportID, reportAction, close: closeManually, openContextMenu, setIsEmojiPickerActive}) => { + renderContent: (closePopover, {reportID, reportAction, currentUserAccountID, close: closeManually, openContextMenu, setIsEmojiPickerActive}) => { const isMini = !closePopover; const closeContextMenu = (onHideCallback?: () => void) => { @@ -313,7 +314,7 @@ const ContextMenuActions: ContextMenuAction[] = [ }; const toggleEmojiAndCloseMenu = (emoji: Emoji, existingReactions: OnyxEntry, preferredSkinTone: number) => { - toggleEmojiReaction(reportID, reportAction, emoji, existingReactions, preferredSkinTone); + toggleEmojiReaction(reportID, reportAction, emoji, existingReactions, preferredSkinTone, currentUserAccountID); closeContextMenu(); setIsEmojiPickerActive?.(false); }; @@ -383,8 +384,8 @@ const ContextMenuActions: ContextMenuAction[] = [ const isDynamicWorkflowRoutedAction = isActionOfType(reportAction, CONST.REPORT.ACTIONS.TYPE.DYNAMIC_EXTERNAL_WORKFLOW_ROUTED); return (type === CONST.CONTEXT_MENU_TYPES.REPORT_ACTION && !isDynamicWorkflowRoutedAction) || (type === CONST.CONTEXT_MENU_TYPES.REPORT && !isUnreadChat); }, - onPress: (closePopover, {reportAction, reportID}) => { - markCommentAsUnread(reportID, reportAction); + onPress: (closePopover, {reportAction, reportID, currentUserAccountID}) => { + markCommentAsUnread(reportID, reportAction, currentUserAccountID); if (closePopover) { hideContextMenu(true, ReportActionComposeFocusManager.focus); } @@ -518,19 +519,19 @@ const ContextMenuActions: ContextMenuAction[] = [ (shouldDisplayThreadReplies || (!isDeletedAction && !isArchivedRoom)) ); }, - onPress: (closePopover, {reportAction, reportID}) => { + onPress: (closePopover, {reportAction, reportID, currentUserAccountID}) => { const childReportNotificationPreference = getChildReportNotificationPreferenceReportUtils(reportAction); const originalReportID = getOriginalReportID(reportID, reportAction); if (closePopover) { hideContextMenu(false, () => { ReportActionComposeFocusManager.focus(); - toggleSubscribeToChildReport(reportAction?.childReportID, reportAction, originalReportID, childReportNotificationPreference); + toggleSubscribeToChildReport(reportAction?.childReportID, currentUserAccountID, reportAction, originalReportID, childReportNotificationPreference); }); return; } ReportActionComposeFocusManager.focus(); - toggleSubscribeToChildReport(reportAction?.childReportID, reportAction, originalReportID, childReportNotificationPreference); + toggleSubscribeToChildReport(reportAction?.childReportID, currentUserAccountID, reportAction, originalReportID, childReportNotificationPreference); }, getDescription: () => {}, sentryLabel: CONST.SENTRY_LABEL.CONTEXT_MENU.JOIN_THREAD, @@ -558,19 +559,19 @@ const ContextMenuActions: ContextMenuAction[] = [ (shouldDisplayThreadReplies || (!isDeletedAction && !isArchivedRoom)) ); }, - onPress: (closePopover, {reportAction, reportID}) => { + onPress: (closePopover, {reportAction, reportID, currentUserAccountID}) => { const childReportNotificationPreference = getChildReportNotificationPreferenceReportUtils(reportAction); const originalReportID = getOriginalReportID(reportID, reportAction); if (closePopover) { hideContextMenu(false, () => { ReportActionComposeFocusManager.focus(); - toggleSubscribeToChildReport(reportAction?.childReportID, reportAction, originalReportID, childReportNotificationPreference); + toggleSubscribeToChildReport(reportAction?.childReportID, currentUserAccountID, reportAction, originalReportID, childReportNotificationPreference); }); return; } ReportActionComposeFocusManager.focus(); - toggleSubscribeToChildReport(reportAction?.childReportID, reportAction, originalReportID, childReportNotificationPreference); + toggleSubscribeToChildReport(reportAction?.childReportID, currentUserAccountID, reportAction, originalReportID, childReportNotificationPreference); }, getDescription: () => {}, sentryLabel: CONST.SENTRY_LABEL.CONTEXT_MENU.LEAVE_THREAD, diff --git a/src/pages/home/report/PureReportActionItem.tsx b/src/pages/home/report/PureReportActionItem.tsx index 1a4a304bea68..0e2a7e1b3bac 100644 --- a/src/pages/home/report/PureReportActionItem.tsx +++ b/src/pages/home/report/PureReportActionItem.tsx @@ -347,6 +347,7 @@ type PureReportActionItemProps = { reactionObject: Emoji, existingReactions: OnyxEntry, paramSkinTone: number, + currentUserAccountID: number, ignoreSkinToneOnCompare: boolean | undefined, ) => void; @@ -417,7 +418,7 @@ type PureReportActionItemProps = { isTryNewDotNVPDismissed?: boolean; /** Current user's account id */ - currentUserAccountID?: number; + currentUserAccountID: number; /** The bank account list */ bankAccountList?: OnyxTypes.BankAccountList | undefined; @@ -769,9 +770,9 @@ function PureReportActionItem({ const toggleReaction = useCallback( (emoji: Emoji, preferredSkinTone: number, ignoreSkinToneOnCompare?: boolean) => { - toggleEmojiReaction(reportID, action, emoji, emojiReactions, preferredSkinTone, ignoreSkinToneOnCompare); + toggleEmojiReaction(reportID, action, emoji, emojiReactions, preferredSkinTone, currentUserAccountID, ignoreSkinToneOnCompare); }, - [reportID, action, emojiReactions, toggleEmojiReaction], + [reportID, action, emojiReactions, toggleEmojiReaction, currentUserAccountID], ); const contextValue = useMemo( diff --git a/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx b/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx index 944099f89ebf..0a9736126678 100644 --- a/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx +++ b/src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx @@ -11,6 +11,7 @@ import type {Emoji} from '@assets/emojis/types'; import type {MeasureParentContainerAndCursorCallback} from '@components/AutoCompleteSuggestions/types'; import Composer from '@components/Composer'; import type {CustomSelectionChangeEvent, TextSelection} from '@components/Composer/types'; +import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; import useKeyboardState from '@hooks/useKeyboardState'; import useLocalize from '@hooks/useLocalize'; import useOnyx from '@hooks/useOnyx'; @@ -168,8 +169,8 @@ const isIOSNative = getPlatform() === CONST.PLATFORM.IOS; * Broadcast that the user is typing. Debounced to limit how often we publish client events. */ const debouncedBroadcastUserIsTyping = lodashDebounce( - (reportID: string) => { - broadcastUserIsTyping(reportID); + (reportID: string, currentUserAccountID: number) => { + broadcastUserIsTyping(reportID, currentUserAccountID); }, 1000, { @@ -250,6 +251,7 @@ function ComposerWithSuggestions({ } return draftComment; }); + const {accountID: currentUserAccountID} = useCurrentUserPersonalDetails(); const commentRef = useRef(value); @@ -444,7 +446,7 @@ function ComposerWithSuggestions({ saveReportDraftComment(reportID, newCommentConverted); } if (newCommentConverted) { - debouncedBroadcastUserIsTyping(reportID); + debouncedBroadcastUserIsTyping(reportID, currentUserAccountID); } }, [ @@ -458,6 +460,7 @@ function ComposerWithSuggestions({ debouncedSaveReportComment, selection?.end, selection?.start, + currentUserAccountID, ], ); diff --git a/src/pages/home/report/ReportActionItem.tsx b/src/pages/home/report/ReportActionItem.tsx index ab6833febcc0..6302e306eeab 100644 --- a/src/pages/home/report/ReportActionItem.tsx +++ b/src/pages/home/report/ReportActionItem.tsx @@ -1,7 +1,7 @@ -import {accountIDSelector} from '@selectors/Session'; import React from 'react'; import type {OnyxCollection, OnyxEntry} from 'react-native-onyx'; import {useBlockedFromConcierge} from '@components/OnyxListItemProvider'; +import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; import useOnyx from '@hooks/useOnyx'; import useOriginalReportID from '@hooks/useOriginalReportID'; import usePolicyForMovingExpenses from '@hooks/usePolicyForMovingExpenses'; @@ -35,7 +35,7 @@ import type {Errors} from '@src/types/onyx/OnyxCommon'; import type {PureReportActionItemProps} from './PureReportActionItem'; import PureReportActionItem from './PureReportActionItem'; -type ReportActionItemProps = Omit & { +type ReportActionItemProps = Omit & { /** All the data of the report collection */ allReports: OnyxCollection; @@ -94,7 +94,7 @@ function ReportActionItem({ const originalReportID = useOriginalReportID(reportID, action); const originalReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${originalReportID}`]; const isOriginalReportArchived = useReportIsArchived(originalReportID); - const [currentUserAccountID] = useOnyx(ONYXKEYS.SESSION, {canBeMissing: false, selector: accountIDSelector}); + const {accountID: currentUserAccountID} = useCurrentUserPersonalDetails(); const [introSelected] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED, {canBeMissing: true}); const [reportMetadata] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_METADATA}${reportID}`, {canBeMissing: true}); const iouReport = allReports?.[`${ONYXKEYS.COLLECTION.REPORT}${getIOUReportIDFromReportActionPreview(action)}`]; diff --git a/src/pages/home/report/ReportFooter.tsx b/src/pages/home/report/ReportFooter.tsx index d2f4d6cb8790..77a3bda2c00f 100644 --- a/src/pages/home/report/ReportFooter.tsx +++ b/src/pages/home/report/ReportFooter.tsx @@ -225,7 +225,12 @@ function ReportFooter({ isSmallSizeLayout={isSmallSizeLayout || isInSidePanel} /> )} - {isArchivedRoom && } + {isArchivedRoom && ( + + )} {!isArchivedRoom && !!isBlockedFromChat && } {!isAnonymousUser && !canWriteInReport && isSystemChat && } {isAdminsOnlyPostingRoom && !isUserPolicyAdmin && !isArchivedRoom && !isAnonymousUser && !isBlockedFromChat && ( diff --git a/src/pages/home/report/UserTypingEventListener.tsx b/src/pages/home/report/UserTypingEventListener.tsx index d72cb1114ddf..48f5c291ea49 100644 --- a/src/pages/home/report/UserTypingEventListener.tsx +++ b/src/pages/home/report/UserTypingEventListener.tsx @@ -1,6 +1,7 @@ import {useIsFocused, useRoute} from '@react-navigation/native'; import {useEffect, useRef} from 'react'; import {InteractionManager} from 'react-native'; +import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; import useOnyx from '@hooks/useOnyx'; import Navigation from '@libs/Navigation/Navigation'; import type {PlatformStackRouteProp} from '@libs/Navigation/PlatformStackNavigation/types'; @@ -16,6 +17,7 @@ type UserTypingEventListenerProps = { }; function UserTypingEventListener({report}: UserTypingEventListenerProps) { const [lastVisitedPath = ''] = useOnyx(ONYXKEYS.LAST_VISITED_PATH, {canBeMissing: true}); + const {accountID: currentUserAccountID} = useCurrentUserPersonalDetails(); const didSubscribeToReportTypingEvents = useRef(false); const reportID = report.reportID; const isFocused = useIsFocused(); @@ -55,7 +57,7 @@ function UserTypingEventListener({report}: UserTypingEventListenerProps) { if (!didSubscribeToReportTypingEvents.current && didCreateReportSuccessfully) { // eslint-disable-next-line @typescript-eslint/no-deprecated interactionTask = InteractionManager.runAfterInteractions(() => { - subscribeToReportTypingEvents(reportID); + subscribeToReportTypingEvents(reportID, currentUserAccountID); didSubscribeToReportTypingEvents.current = true; }); } @@ -76,7 +78,7 @@ function UserTypingEventListener({report}: UserTypingEventListenerProps) { } interactionTask.cancel(); }; - }, [isFocused, report.pendingFields, didSubscribeToReportTypingEvents, lastVisitedPath, reportID, route?.params?.reportID]); + }, [isFocused, report.pendingFields, didSubscribeToReportTypingEvents, lastVisitedPath, reportID, currentUserAccountID, route?.params?.reportID]); return null; } diff --git a/src/pages/settings/Report/NotificationPreferencePage.tsx b/src/pages/settings/Report/NotificationPreferencePage.tsx index 7bb0a6a06c8e..4a54a35482a7 100644 --- a/src/pages/settings/Report/NotificationPreferencePage.tsx +++ b/src/pages/settings/Report/NotificationPreferencePage.tsx @@ -6,6 +6,7 @@ import HeaderWithBackButton from '@components/HeaderWithBackButton'; import ScreenWrapper from '@components/ScreenWrapper'; import SelectionList from '@components/SelectionList'; import RadioListItem from '@components/SelectionList/ListItem/RadioListItem'; +import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; import useLocalize from '@hooks/useLocalize'; import useReportIsArchived from '@hooks/useReportIsArchived'; import type {PlatformStackRouteProp, PlatformStackScreenProps} from '@libs/Navigation/PlatformStackNavigation/types'; @@ -23,6 +24,7 @@ function NotificationPreferencePage({report}: NotificationPreferencePageProps) { const route = useRoute>(); const {translate} = useLocalize(); const isReportArchived = useReportIsArchived(report?.reportID); + const {accountID: currentUserAccountID} = useCurrentUserPersonalDetails(); const isMoneyRequest = isMoneyRequestReport(report); const currentNotificationPreference = getReportNotificationPreference(report); const shouldDisableNotificationPreferences = @@ -42,10 +44,10 @@ function NotificationPreferencePage({report}: NotificationPreferencePageProps) { const updateNotificationPreferenceForReportAction = useCallback( (value: ValueOf) => { - updateNotificationPreference(report.reportID, currentNotificationPreference, value, undefined, undefined); + updateNotificationPreference(report.reportID, currentNotificationPreference, value, currentUserAccountID, undefined, undefined); goBack(); }, - [report.reportID, currentNotificationPreference, goBack], + [report.reportID, currentNotificationPreference, currentUserAccountID, goBack], ); return ( diff --git a/tests/actions/ReportTest.ts b/tests/actions/ReportTest.ts index 7f5435ea39b8..740e124c3713 100644 --- a/tests/actions/ReportTest.ts +++ b/tests/actions/ReportTest.ts @@ -397,7 +397,7 @@ describe('actions/Report', () => { expect(ReportUtils.isUnreadWithMention(report)).toBe(false); // When the user manually marks a message as "unread" - Report.markCommentAsUnread(REPORT_ID, reportActions['1']); + Report.markCommentAsUnread(REPORT_ID, reportActions['1'], USER_1_ACCOUNT_ID); return waitForBatchedUpdates(); }) .then(() => { @@ -521,7 +521,7 @@ describe('actions/Report', () => { expect(ReportUtils.isUnread(report, undefined, undefined)).toBe(false); // When the user manually marks a message as "unread" - Report.markCommentAsUnread(REPORT_ID, reportActions[400]); + Report.markCommentAsUnread(REPORT_ID, reportActions[400], USER_1_ACCOUNT_ID); return waitForBatchedUpdates(); }) .then(() => { @@ -727,7 +727,7 @@ describe('actions/Report', () => { if (reportAction) { // Add a reaction to the comment - Report.toggleEmojiReaction(REPORT_ID, reportAction, EMOJI, reportActionsReactions[0], CONST.EMOJI_DEFAULT_SKIN_TONE); + Report.toggleEmojiReaction(REPORT_ID, reportAction, EMOJI, reportActionsReactions[0], CONST.EMOJI_DEFAULT_SKIN_TONE, TEST_USER_ACCOUNT_ID); } return waitForBatchedUpdates(); }) @@ -747,7 +747,7 @@ describe('actions/Report', () => { if (reportAction) { // Now we remove the reaction - Report.toggleEmojiReaction(REPORT_ID, reportAction, EMOJI, reportActionReaction, CONST.EMOJI_DEFAULT_SKIN_TONE); + Report.toggleEmojiReaction(REPORT_ID, reportAction, EMOJI, reportActionReaction, CONST.EMOJI_DEFAULT_SKIN_TONE, TEST_USER_ACCOUNT_ID); } return waitForBatchedUpdates(); }) @@ -762,7 +762,7 @@ describe('actions/Report', () => { if (reportAction) { // Add the same reaction to the same report action with a different skin tone - Report.toggleEmojiReaction(REPORT_ID, reportAction, EMOJI, reportActionsReactions[0], CONST.EMOJI_DEFAULT_SKIN_TONE); + Report.toggleEmojiReaction(REPORT_ID, reportAction, EMOJI, reportActionsReactions[0], CONST.EMOJI_DEFAULT_SKIN_TONE, TEST_USER_ACCOUNT_ID); } return waitForBatchedUpdates() .then(() => { @@ -770,7 +770,7 @@ describe('actions/Report', () => { const reportActionReaction = reportActionsReactions[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS_REACTIONS}${reportActionID}`]; if (reportAction) { - Report.toggleEmojiReaction(REPORT_ID, reportAction, EMOJI, reportActionReaction, EMOJI_SKIN_TONE); + Report.toggleEmojiReaction(REPORT_ID, reportAction, EMOJI, reportActionReaction, EMOJI_SKIN_TONE, TEST_USER_ACCOUNT_ID); } return waitForBatchedUpdates(); }) @@ -795,7 +795,7 @@ describe('actions/Report', () => { if (reportAction) { // Now we remove the reaction, and expect that both variations are removed - Report.toggleEmojiReaction(REPORT_ID, reportAction, EMOJI, reportActionReaction, CONST.EMOJI_DEFAULT_SKIN_TONE); + Report.toggleEmojiReaction(REPORT_ID, reportAction, EMOJI, reportActionReaction, CONST.EMOJI_DEFAULT_SKIN_TONE, TEST_USER_ACCOUNT_ID); } return waitForBatchedUpdates(); }) @@ -855,7 +855,7 @@ describe('actions/Report', () => { if (resultAction) { // Add a reaction to the comment - Report.toggleEmojiReaction(REPORT_ID, resultAction, EMOJI, {}, CONST.EMOJI_DEFAULT_SKIN_TONE); + Report.toggleEmojiReaction(REPORT_ID, resultAction, EMOJI, {}, CONST.EMOJI_DEFAULT_SKIN_TONE, TEST_USER_ACCOUNT_ID); } return waitForBatchedUpdates(); }) @@ -867,7 +867,7 @@ describe('actions/Report', () => { // should get removed instead of added again. const reportActionReaction = reportActionsReactions[`${ONYXKEYS.COLLECTION.REPORT_ACTIONS_REACTIONS}${resultAction?.reportActionID}`]; if (resultAction) { - Report.toggleEmojiReaction(REPORT_ID, resultAction, EMOJI, reportActionReaction, 2); + Report.toggleEmojiReaction(REPORT_ID, resultAction, EMOJI, reportActionReaction, 2, TEST_USER_ACCOUNT_ID); } return waitForBatchedUpdates(); }) @@ -1487,7 +1487,7 @@ describe('actions/Report', () => { await waitForBatchedUpdates(); - Report.toggleEmojiReaction(REPORT_ID, newReportAction, {name: 'smile', code: 'πŸ˜„'}, {}, CONST.EMOJI_DEFAULT_SKIN_TONE); + Report.toggleEmojiReaction(REPORT_ID, newReportAction, {name: 'smile', code: 'πŸ˜„'}, {}, CONST.EMOJI_DEFAULT_SKIN_TONE, TEST_USER_ACCOUNT_ID); Report.toggleEmojiReaction( REPORT_ID, newReportAction, @@ -1508,6 +1508,7 @@ describe('actions/Report', () => { }, }, CONST.EMOJI_DEFAULT_SKIN_TONE, + TEST_USER_ACCOUNT_ID, ); await waitForBatchedUpdates(); @@ -1588,7 +1589,7 @@ describe('actions/Report', () => { // wait for Onyx.connect execute the callback and start processing the queue await Promise.resolve(); - Report.toggleEmojiReaction(REPORT_ID, reportAction, {name: 'smile', code: 'πŸ˜„'}, {}, CONST.EMOJI_DEFAULT_SKIN_TONE); + Report.toggleEmojiReaction(REPORT_ID, reportAction, {name: 'smile', code: 'πŸ˜„'}, {}, CONST.EMOJI_DEFAULT_SKIN_TONE, TEST_USER_ACCOUNT_ID); Report.toggleEmojiReaction( REPORT_ID, reportAction, @@ -1609,6 +1610,7 @@ describe('actions/Report', () => { }, }, CONST.EMOJI_DEFAULT_SKIN_TONE, + TEST_USER_ACCOUNT_ID, ); await waitForBatchedUpdates(); @@ -2182,9 +2184,10 @@ describe('actions/Report', () => { }); describe('updateDescription', () => { + const currentUserAccountID = 1; it('should not call UpdateRoomDescription API if the description is not changed', async () => { global.fetch = TestHelper.getGlobalFetchMock(); - Report.updateDescription('1', '

test

', '# test'); + Report.updateDescription('1', '

test

', '# test', currentUserAccountID); await waitForBatchedUpdates(); @@ -2201,7 +2204,7 @@ describe('actions/Report', () => { await Onyx.set(`${ONYXKEYS.COLLECTION.REPORT}${report.reportID}`, report); mockFetch?.fail?.(); - Report.updateDescription('1', '

test

', '# test1'); + Report.updateDescription('1', '

test

', '# test1', currentUserAccountID); await waitForBatchedUpdates(); let updateReport: OnyxEntry; @@ -2211,6 +2214,8 @@ describe('actions/Report', () => { callback: (val) => (updateReport = val), }); expect(updateReport?.description).toBe('

test

'); + expect(updateReport?.lastActorAccountID).toBe(currentUserAccountID); + mockFetch.mockReset(); }); }); diff --git a/tests/ui/PureReportActionItemTest.tsx b/tests/ui/PureReportActionItemTest.tsx index cda560122c28..782f1c451642 100644 --- a/tests/ui/PureReportActionItemTest.tsx +++ b/tests/ui/PureReportActionItemTest.tsx @@ -99,6 +99,7 @@ describe('PureReportActionItem', () => { taskReport={undefined} linkedReport={undefined} iouReportOfLinkedReport={undefined} + currentUserAccountID={ACTOR_ACCOUNT_ID} />
@@ -277,6 +278,7 @@ describe('PureReportActionItem', () => { linkedReport={undefined} iouReportOfLinkedReport={undefined} reportMetadata={reportMetadata} + currentUserAccountID={ACTOR_ACCOUNT_ID} /> @@ -333,6 +335,7 @@ describe('PureReportActionItem', () => { taskReport={undefined} linkedReport={undefined} iouReportOfLinkedReport={undefined} + currentUserAccountID={ACTOR_ACCOUNT_ID} /> diff --git a/tests/ui/UnreadIndicatorsTest.tsx b/tests/ui/UnreadIndicatorsTest.tsx index 6407045cd712..c9b27b702b0b 100644 --- a/tests/ui/UnreadIndicatorsTest.tsx +++ b/tests/ui/UnreadIndicatorsTest.tsx @@ -429,7 +429,7 @@ describe('Unread Indicators', () => { .then(() => { // It's difficult to trigger marking a report comment as unread since we would have to mock the long press event and then // another press on the context menu item so we will do it via the action directly and then test if the UI has updated properly - markCommentAsUnread(REPORT_ID, createdReportAction); + markCommentAsUnread(REPORT_ID, createdReportAction, USER_A_ACCOUNT_ID); return waitForBatchedUpdates(); }) .then(() => { @@ -528,7 +528,7 @@ describe('Unread Indicators', () => { expect(unreadIndicator).toHaveLength(0); // Mark a previous comment as unread and verify the unread action indicator returns - markCommentAsUnread(REPORT_ID, createdReportAction); + markCommentAsUnread(REPORT_ID, createdReportAction, USER_A_ACCOUNT_ID); return waitForBatchedUpdates(); }) .then(() => { @@ -612,7 +612,7 @@ describe('Unread Indicators', () => { const firstNewReportAction = reportActions ? lastItem(reportActions) : undefined; if (firstNewReportAction) { - markCommentAsUnread(REPORT_ID, firstNewReportAction); + markCommentAsUnread(REPORT_ID, firstNewReportAction, USER_A_ACCOUNT_ID); await waitForBatchedUpdates(); @@ -755,7 +755,7 @@ describe('Unread Indicators', () => { lastVisibleActionCreated: reportAction11CreatedDate, }); - markCommentAsUnread(REPORT_ID, {reportActionID: -1} as unknown as ReportAction); // Marking the chat as unread from LHN passing a dummy reportActionID + markCommentAsUnread(REPORT_ID, {reportActionID: -1} as unknown as ReportAction, USER_A_ACCOUNT_ID); // Marking the chat as unread from LHN passing a dummy reportActionID await waitForBatchedUpdates(); const hintText = TestHelper.translateLocal('accessibilityHints.chatUserDisplayNames'); @@ -763,4 +763,23 @@ describe('Unread Indicators', () => { expect(displayNameTexts).toHaveLength(1); expect((displayNameTexts.at(0)?.props?.style as TextStyle)?.fontWeight).toBe(FontUtils.fontWeight.bold); }); + + it('Mark the last comment as unread should set lastReadTime to the last action’s creation time', async () => { + await signInAndGetAppWithUnreadChat(); + await navigateToSidebarOption(0); + + const report = await OnyxUtils.get(`${ONYXKEYS.COLLECTION.REPORT}${REPORT_ID}`); + + // When USER_A add a comment + addComment(report, REPORT_ID, [], 'Current User Comment', CONST.DEFAULT_TIME_ZONE); + await waitForBatchedUpdates(); + + // Then USER_A mark the report as unread + markCommentAsUnread(REPORT_ID, {reportActionID: -1} as unknown as ReportAction, USER_A_ACCOUNT_ID); + await waitForBatchedUpdates(); + + // Then the lastReadTime of report should same as last action from USER_B + const updatedReport = await OnyxUtils.get(`${ONYXKEYS.COLLECTION.REPORT}${REPORT_ID}`); + expect(updatedReport?.lastReadTime).toBe(DateUtils.subtractMillisecondsFromDateTime(reportAction9CreatedDate, 1)); + }); }); diff --git a/tests/ui/components/HeaderViewTest.tsx b/tests/ui/components/HeaderViewTest.tsx index 4f7ed8429191..c7e2b70f9f1c 100644 --- a/tests/ui/components/HeaderViewTest.tsx +++ b/tests/ui/components/HeaderViewTest.tsx @@ -1,12 +1,17 @@ -import {act, render, screen} from '@testing-library/react-native'; +import {act, fireEvent, render, screen} from '@testing-library/react-native'; import React from 'react'; import Onyx from 'react-native-onyx'; import type {KeyValueMapping} from 'react-native-onyx'; +import ComposeProviders from '@components/ComposeProviders'; import {LocaleContextProvider} from '@components/LocaleContextProvider'; import OnyxListItemProvider from '@components/OnyxListItemProvider'; +import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails'; import type Navigation from '@libs/Navigation/Navigation'; import {buildOptimisticCreatedReportForUnapprovedAction} from '@libs/ReportUtils'; import HeaderView from '@pages/home/HeaderView'; +import {joinRoom} from '@userActions/Report'; +// eslint-disable-next-line no-restricted-syntax +import type * as ReportType from '@userActions/Report'; import CONST from '@src/CONST'; import ONYXKEYS from '@src/ONYXKEYS'; import type {ReportAction} from '@src/types/onyx'; @@ -22,8 +27,22 @@ jest.mock('@react-navigation/native', () => { }); jest.mock('@hooks/useCurrentUserPersonalDetails'); +jest.mock('@userActions/Report', () => ({ + ...jest.requireActual('@userActions/Report'), + joinRoom: jest.fn(), +})); + +const mockUseCurrentUserPersonalDetails = useCurrentUserPersonalDetails as jest.MockedFunction; +const currentUserAccountID = 1; describe('HeaderView', () => { + beforeEach(() => { + // Set up default mock return value + mockUseCurrentUserPersonalDetails.mockReturnValue({ + accountID: currentUserAccountID, + }); + }); + afterEach(() => { jest.clearAllMocks(); }); @@ -83,6 +102,36 @@ describe('HeaderView', () => { expect(screen.getByTestId('DisplayNames')).toHaveTextContent(displayName); }); + it('should display join button', async () => { + // Given an policy room header + const report = { + ...createRandomReport(1, CONST.REPORT.CHAT_TYPE.POLICY_ROOM), + reportName: 'Test Room', + notificationPreference: CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN, + }; + + render( + + {}} + parentReportAction={null} + reportID={report.reportID} + shouldUseNarrowLayout + /> + , + ); + + await waitForBatchedUpdatesWithAct(); + // When the header display the Join button + const joinButton = screen.getByText('Join'); + expect(joinButton).toBeTruthy(); + + // Then the joinRoom action should be called when the user presses the Join button + fireEvent.press(joinButton); + expect(joinRoom).toHaveBeenCalledWith(report, currentUserAccountID); + }); + it('should display correct title for report with CREATED_REPORT_FOR_UNAPPROVED_TRANSACTIONS parent action', async () => { // Given a chat thread with a CREATED_REPORT_FOR_UNAPPROVED_TRANSACTIONS parent action const originalReportID = '100';