Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 8 additions & 3 deletions src/DeepLinkHandler.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ function DeepLinkHandler({onInitialUrl}: DeepLinkHandlerProps) {

const [allReports, allReportsMetadata] = useOnyx(ONYXKEYS.COLLECTION.REPORT);
const [isLoadingApp = true] = useOnyx(ONYXKEYS.IS_LOADING_APP);
const [, sessionMetadata] = useOnyx(ONYXKEYS.SESSION);
const [session, sessionMetadata] = useOnyx(ONYXKEYS.SESSION);
const [conciergeReportID, conciergeReportIDMetadata] = useOnyx(ONYXKEYS.CONCIERGE_REPORT_ID);
const [introSelected, introSelectedMetadata] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED);
const [isSelfTourViewed, isSelfTourViewedMetadata] = useOnyx(ONYXKEYS.NVP_ONBOARDING, {selector: hasSeenTourSelector});
Expand Down Expand Up @@ -184,8 +184,13 @@ function DeepLinkHandler({onInitialUrl}: DeepLinkHandlerProps) {
return;
}
hasRefetchedPublicRoom.current = true;
Report.openReport({reportID, introSelected, betas});
}, [isLoadingApp, allReports, introSelected, betas]);
Report.openReport({
reportID,
introSelected,
betas,
currentUserAccountID: session?.accountID,
});
}, [isLoadingApp, allReports, introSelected, betas, session?.accountID]);

return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -622,15 +622,21 @@ function MoneyRequestReportActionsList({onLayout}: MoneyRequestReportListProps)
setIsFloatingMessageCounterVisible(false);

if (!hasNewestReportAction) {
openReport({reportID, introSelected, betas, hasReportActions: true});
openReport({
reportID,
introSelected,
betas,
hasReportActions: true,
currentUserAccountID,
});
reportScrollManager.scrollToEnd();
return;
}

reportScrollManager.scrollToEnd();
readActionSkipped.current = false;
readNewestAction(reportID, true);
}, [setIsFloatingMessageCounterVisible, hasNewestReportAction, reportScrollManager, reportID, introSelected, betas]);
}, [setIsFloatingMessageCounterVisible, hasNewestReportAction, reportScrollManager, reportID, introSelected, betas, currentUserAccountID]);

const scrollToNewTransaction = useCallback(
(pageY: number) => {
Expand Down
8 changes: 7 additions & 1 deletion src/components/TestDrive/TestDriveDemo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,13 @@ function TestDriveDemo() {
setSelfTourViewed();
if (conciergeReportID && !hasCalledOpenReportRef.current) {
hasCalledOpenReportRef.current = true;
openReport({reportID: conciergeReportID, introSelected, betas, hasReportActions: hasConciergeReportActions});
openReport({
reportID: conciergeReportID,
introSelected,
betas,
hasReportActions: hasConciergeReportActions,
currentUserAccountID: currentUserPersonalDetails.accountID,
});
}
return;
}
Expand Down
4 changes: 3 additions & 1 deletion src/hooks/useReportActionsScroll.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import type {OnyxEntry} from 'react-native-onyx';
import {useRoute} from '@react-navigation/native';
import {useEffect, useEffectEvent, useState} from 'react';

import useCurrentUserPersonalDetails from './useCurrentUserPersonalDetails';
import useNetworkWithOfflineStatus from './useNetworkWithOfflineStatus';
import useOnyx from './useOnyx';
import usePrevious from './usePrevious';
Expand Down Expand Up @@ -164,6 +165,7 @@ function useReportActionsScroll({
const {isOffline} = useNetworkWithOfflineStatus();
const [introSelected] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED);
const [betas] = useOnyx(ONYXKEYS.BETAS);
const {accountID: currentUserAccountID} = useCurrentUserPersonalDetails();
const [reportLoadingState] = useOnyx(`${ONYXKEYS.COLLECTION.RAM_ONLY_REPORT_LOADING_STATE}${reportID}`);
const [reportActionPages] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS_PAGES}${getNonEmptyStringOnyxID(reportID)}`);
const prevIsLoadingInitialReportActions = usePrevious(reportLoadingState?.isLoadingInitialReportActions);
Expand Down Expand Up @@ -347,7 +349,7 @@ function useReportActionsScroll({
if (!Navigation.getReportRHPActiveRoute()) {
Navigation.navigate(ROUTES.REPORT_WITH_ID.getRoute(reportID, undefined, undefined, backTo));
}
openReport({reportID, introSelected, betas, hasReportActions: true});
openReport({reportID, introSelected, betas, hasReportActions: true, currentUserAccountID});
reportScrollManager.scrollToBottom();
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ function AuthScreensInitHandler() {
} else if (SessionUtils.didUserLogInDuringSession()) {
const reportID = getReportIDFromLink(initialURL ?? null);
if (reportID && !isAuthenticatedAtStartup) {
Report.openReport({reportID, introSelected, betas, hasReportActions: false});
Report.openReport({reportID, introSelected, betas, hasReportActions: false, currentUserAccountID: session?.accountID});
// Don't want to call `openReport` again when logging out and then logging in
setIsAuthenticatedAtStartup(true);
}
Expand Down
10 changes: 7 additions & 3 deletions src/libs/actions/Report/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2389,6 +2389,7 @@ function navigateToAndOpenReport(
newReportObject: fallbackChat,
isSelfTourViewed,
betas,
currentUserAccountID,
});

navigateToReport(fallbackChat.reportID, {shouldDismissModal, ...linkToOptions});
Expand Down Expand Up @@ -2425,7 +2426,7 @@ function navigateToAndOpenReport(
});

// Re-open existing chats to re-validate server-side access and refresh stale local state.
openReport({reportID: chat.reportID, introSelected, isSelfTourViewed, betas});
openReport({reportID: chat.reportID, introSelected, isSelfTourViewed, betas, currentUserAccountID});
navigateToReport(chat.reportID, {shouldDismissModal, ...linkToOptions});
}

Expand Down Expand Up @@ -2522,6 +2523,7 @@ function navigateToAndOpenReportWithAccountIDs(
participants,
personalDetails,
betas,
currentUserAccountID,
});

navigateToReport(fallbackChat.reportID, {shouldDismissModal: false});
Expand Down Expand Up @@ -2558,7 +2560,7 @@ function navigateToAndOpenReportWithAccountIDs(
});

// Re-open existing chats to re-validate server-side access and refresh stale local state.
openReport({reportID: chat.reportID, introSelected, isSelfTourViewed, hasCompletedGuidedSetupFlow, betas});
openReport({reportID: chat.reportID, introSelected, isSelfTourViewed, hasCompletedGuidedSetupFlow, betas, currentUserAccountID});
navigateToReport(chat.reportID, {shouldDismissModal: false});
}

Expand Down Expand Up @@ -2648,6 +2650,7 @@ function createChildReport(
isNewThread: true,
betas,
isSelfTourViewed,
currentUserAccountID,
});
} else {
Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${childReportID}`, newChat);
Expand Down Expand Up @@ -3583,7 +3586,7 @@ function toggleSubscribeToChildReport(
personalDetails: OnyxEntry<PersonalDetailsList>,
) {
if (childReportID) {
openReport({reportID: childReportID, introSelected, betas, isSelfTourViewed, hasCompletedGuidedSetupFlow});
openReport({reportID: childReportID, introSelected, betas, isSelfTourViewed, hasCompletedGuidedSetupFlow, currentUserAccountID});
const parentReportActionID = parentReportAction.reportActionID;
if (!prevNotificationPreference || isHiddenForCurrentUser(prevNotificationPreference)) {
updateNotificationPreference(
Expand Down Expand Up @@ -3630,6 +3633,7 @@ function toggleSubscribeToChildReport(
isSelfTourViewed,
hasCompletedGuidedSetupFlow,
betas,
currentUserAccountID,
});
const notificationPreference = isHiddenForCurrentUser(prevNotificationPreference) ? CONST.REPORT.NOTIFICATION_PREFERENCE.ALWAYS : CONST.REPORT.NOTIFICATION_PREFERENCE.HIDDEN;
updateNotificationPreference(newChat.reportID, prevNotificationPreference, notificationPreference, currentUserAccountID, parentReport?.reportID, parentReportAction.reportActionID);
Expand Down
6 changes: 3 additions & 3 deletions src/pages/inbox/ReportFetchHandler.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ function ReportFetchHandler() {
return;
}

openReport({reportID: reportIDFromRoute, introSelected, reportActionID: reportActionIDFromRoute, betas, hasReportActions});
openReport({reportID: reportIDFromRoute, introSelected, reportActionID: reportActionIDFromRoute, betas, hasReportActions, currentUserAccountID});
});

const createOneTransactionThread = useEffectEvent(() => {
Expand Down Expand Up @@ -210,15 +210,15 @@ function ReportFetchHandler() {
if (!shouldUseNarrowLayout || !isChatThread(report) || !isHiddenForCurrentUser(report) || isTransactionThreadView) {
return;
}
openReport({reportID, introSelected, betas, hasReportActions});
openReport({reportID, introSelected, betas, hasReportActions, currentUserAccountID});
});

const joinPublicRoomIfNeeded = useEffectEvent(() => {
// Return early if the viewing public room is the current report since we will fetch the current report in another function
if (!viewingPublicRoomReportID || viewingPublicRoomReportID === reportIDFromRoute) {
return;
}
openReport({reportID: viewingPublicRoomReportID, introSelected, betas, hasReportActions: hasViewingPublicRoomReportActions});
openReport({reportID: viewingPublicRoomReportID, introSelected, betas, hasReportActions: hasViewingPublicRoomReportActions, currentUserAccountID});
});

// Effect order below matches the original declaration order in ReportScreen.tsx.
Expand Down
3 changes: 3 additions & 0 deletions src/pages/inbox/report/useReportActionsNewActionLiveTail.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
import type useReportScrollManager from '@hooks/useReportScrollManager';

import type {OpenReportActionParams} from '@libs/actions/Report';
Expand Down Expand Up @@ -75,6 +76,7 @@ function useReportActionsNewActionLiveTail({
prevIsLoadingInitialReportActions,
reportLoadingState,
}: UseReportActionsNewActionLiveTailParams) {
const {accountID: currentUserAccountID} = useCurrentUserPersonalDetails();
const liveTailJumpRef = useRef<{stage: LiveTailJumpStage}>({stage: 'idle'});
const [isScrollToBottomEnabled, setIsScrollToBottomEnabled] = useState(false);

Expand Down Expand Up @@ -107,6 +109,7 @@ function useReportActionsNewActionLiveTail({
introSelected,
betas,
hasReportActions: true,
currentUserAccountID,
});
}
return;
Expand Down
11 changes: 9 additions & 2 deletions src/pages/inbox/report/withReportAndReportActionOrNotFound.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import FullscreenLoadingIndicator from '@components/FullscreenLoadingIndicator';

import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
import useOnyx from '@hooks/useOnyx';
import useParentReportAction from '@hooks/useParentReportAction';
import useReportIsArchived from '@hooks/useReportIsArchived';
Expand Down Expand Up @@ -55,6 +56,7 @@ function WithReportOrNotFoundImpl<TProps extends WithReportAndReportActionOrNotF
const [betas] = useOnyx(ONYXKEYS.BETAS);
const [reportActions] = useOnyx(`${ONYXKEYS.COLLECTION.REPORT_ACTIONS}${props.route.params.reportID}`);
const [introSelected] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED);
const {accountID: currentUserAccountID} = useCurrentUserPersonalDetails();

const parentReportAction = useParentReportAction(report);
let linkedReportAction: OnyxEntry<OnyxTypes.ReportAction> = reportActions?.[`${props.route.params.reportActionID}`];
Expand All @@ -72,9 +74,14 @@ function WithReportOrNotFoundImpl<TProps extends WithReportAndReportActionOrNotF
if (!shouldUseNarrowLayout || (!isEmptyObject(report) && !isEmptyObject(linkedReportAction))) {
return;
}
openReport({reportID: props.route.params.reportID, introSelected, betas});
openReport({
Comment thread
truph01 marked this conversation as resolved.
reportID: props.route.params.reportID,
introSelected,
betas,
currentUserAccountID,
});
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [shouldUseNarrowLayout, props.route.params.reportID]);
}, [shouldUseNarrowLayout, props.route.params.reportID, currentUserAccountID]);

// Perform all the loading checks
const isLoadingReport = isLoadingReportData && !report?.reportID;
Expand Down
6 changes: 4 additions & 2 deletions src/pages/inbox/report/withReportOrNotFound.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import FullscreenLoadingIndicator from '@components/FullscreenLoadingIndicator';

import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
import useOnyx from '@hooks/useOnyx';
import useReportIsArchived from '@hooks/useReportIsArchived';

Expand Down Expand Up @@ -91,6 +92,7 @@ export default function (shouldRequireReportID = true): <TProps extends WithRepo
const [reportLoadingState] = useOnyx(`${ONYXKEYS.COLLECTION.RAM_ONLY_REPORT_LOADING_STATE}${reportID}`);
const [isLoadingReportData] = useOnyx(ONYXKEYS.IS_LOADING_REPORT_DATA);
const [introSelected] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED);
const {accountID: currentUserAccountID} = useCurrentUserPersonalDetails();
const isFocused = useIsFocused();
const contentShown = React.useRef(false);
const isReportIdInRoute = !!reportID?.length;
Expand All @@ -107,9 +109,9 @@ export default function (shouldRequireReportID = true): <TProps extends WithRepo
return;
}
Comment thread
truph01 marked this conversation as resolved.

openReport({reportID, introSelected, betas});
openReport({reportID, introSelected, betas, currentUserAccountID});
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [shouldFetchReport, isReportLoaded, reportID]);
}, [shouldFetchReport, isReportLoaded, reportID, currentUserAccountID]);

if (shouldRequireReportID || isReportIdInRoute) {
const shouldShowFullScreenLoadingIndicator = !isReportLoaded && (isLoadingReportData !== false || shouldFetchReport);
Expand Down
10 changes: 9 additions & 1 deletion src/pages/workspace/rooms/WorkspaceRoomsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import ScreenWrapper from '@components/ScreenWrapper';
import WorkspaceRoomsTable from '@components/Tables/WorkspaceRoomsTable';
import type {WorkspaceRoomRowData} from '@components/Tables/WorkspaceRoomsTable';

import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
import {useMemoizedLazyExpensifyIcons, useMemoizedLazyIllustrations} from '@hooks/useLazyAsset';
import useLocalize from '@hooks/useLocalize';
import useOnyx from '@hooks/useOnyx';
Expand Down Expand Up @@ -57,6 +58,7 @@ function WorkspaceRoomsPage({route}: WorkspaceRoomsPageProps) {
const personalDetails = usePersonalDetails();
const [introSelected] = useOnyx(ONYXKEYS.NVP_INTRO_SELECTED);
const [betas] = useOnyx(ONYXKEYS.BETAS);
const {accountID: currentUserAccountID} = useCurrentUserPersonalDetails();

const [policyReports] = useOnyx(
ONYXKEYS.COLLECTION.REPORT,
Expand All @@ -81,7 +83,13 @@ function WorkspaceRoomsPage({route}: WorkspaceRoomsPageProps) {
// Admins open the details RHP directly instead of the room report, so the report is never fetched via ReportScreen.
// Fetch it here so the RHP has full data (participants, metadata) for Join, Invite and renaming.
// shouldMarkAsRead is false because the user only views the room details, not the conversation itself.
openReport({reportID: report.reportID, introSelected, betas, shouldMarkAsRead: false});
openReport({
reportID: report.reportID,
introSelected,
betas,
shouldMarkAsRead: false,
currentUserAccountID,
});
Navigation.navigate(createDynamicRoute(DYNAMIC_ROUTES.REPORT_DETAILS.getRoute(report.reportID)));
return;
}
Expand Down
29 changes: 29 additions & 0 deletions tests/unit/ReportActionsUtilsTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2366,6 +2366,35 @@ describe('ReportActionsUtils', () => {
const actual = ReportActionsUtils.shouldReportActionBeVisible(reportAction, reportAction.reportActionID, true);
expect(actual).toBe(true);
});

it('should return false for a whisper targeted to another user when currentUserAccountID is provided', () => {
const OTHER_USER_ACCOUNT_ID = 999;
const CURRENT_USER_ACCOUNT_ID = 123;
const reportAction = {
actionName: CONST.REPORT.ACTIONS.TYPE.ADD_COMMENT,
reportActionID: '1',
created: '2025-09-29',
message: [{html: 'secret', type: 'COMMENT', text: 'secret', whisperedTo: [OTHER_USER_ACCOUNT_ID]}],
originalMessage: {html: 'secret', whisperedTo: [OTHER_USER_ACCOUNT_ID]},
} as ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.ADD_COMMENT>;

const actual = ReportActionsUtils.shouldReportActionBeVisible(reportAction, reportAction.reportActionID, true, CURRENT_USER_ACCOUNT_ID);
expect(actual).toBe(false);
});

it('should return true for a whisper targeted to the current user when currentUserAccountID is provided', () => {
const CURRENT_USER_ACCOUNT_ID = 123;
const reportAction = {
actionName: CONST.REPORT.ACTIONS.TYPE.ADD_COMMENT,
reportActionID: '1',
created: '2025-09-29',
message: [{html: 'secret', type: 'COMMENT', text: 'secret', whisperedTo: [CURRENT_USER_ACCOUNT_ID]}],
originalMessage: {html: 'secret', whisperedTo: [CURRENT_USER_ACCOUNT_ID]},
} as ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.ADD_COMMENT>;

const actual = ReportActionsUtils.shouldReportActionBeVisible(reportAction, reportAction.reportActionID, true, CURRENT_USER_ACCOUNT_ID);
expect(actual).toBe(true);
});
});

describe('getPolicyChangeLogUpdateEmployee', () => {
Expand Down
Loading