Skip to content
7 changes: 7 additions & 0 deletions src/libs/ReportActionsUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
type MemberChangeMessageElement = MessageTextElement | MemberChangeMessageUserMentionElement | MemberChangeMessageRoomReferenceElement;

let allReportActions: OnyxCollection<ReportActions>;
Onyx.connect({

Check warning on line 61 in src/libs/ReportActionsUtils.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.REPORT_ACTIONS,
waitForCollectionCallback: true,
callback: (actions) => {
Expand All @@ -70,7 +70,7 @@
});

let allReports: OnyxCollection<Report>;
Onyx.connect({

Check warning on line 73 in src/libs/ReportActionsUtils.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.REPORT,
waitForCollectionCallback: true,
callback: (value) => {
Expand All @@ -79,14 +79,14 @@
});

let isNetworkOffline = false;
Onyx.connect({

Check warning on line 82 in src/libs/ReportActionsUtils.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.NETWORK,
callback: (val) => (isNetworkOffline = val?.isOffline ?? false),
});

let currentUserAccountID: number | undefined;
let currentEmail = '';
Onyx.connect({

Check warning on line 89 in src/libs/ReportActionsUtils.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.SESSION,
callback: (value) => {
// When signed out, value is undefined
Expand Down Expand Up @@ -3400,6 +3400,12 @@
return getOriginalMessage(action)?.to;
}

function isSystemUserMentioned(action: OnyxInputOrEntry<ReportAction<typeof CONST.REPORT.ACTIONS.TYPE.ACTIONABLE_MENTION_WHISPER>>): boolean {
const mentionedUsers = getOriginalMessage(action)?.inviteeAccountIDs;
const systemAccountIDs = new Set(Object.values(CONST.ACCOUNT_ID));
return mentionedUsers?.some((accountID) => systemAccountIDs.has(accountID)) ?? false;
}

export {
doesReportHaveVisibleActions,
extractLinksFromMessageHtml,
Expand Down Expand Up @@ -3585,6 +3591,7 @@
isPendingHide,
filterOutDeprecatedReportActions,
getActionableCardFraudAlertMessage,
isSystemUserMentioned,
};

export type {LastVisibleMessage};
8 changes: 8 additions & 0 deletions src/libs/actions/Report.ts
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@
let currentUserAccountID = -1;
let currentUserEmail: string | undefined;

Onyx.connect({

Check warning on line 279 in src/libs/actions/Report.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.SESSION,
callback: (value) => {
// When signed out, val is undefined
Expand All @@ -289,7 +289,7 @@
},
});

Onyx.connect({

Check warning on line 292 in src/libs/actions/Report.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.CONCIERGE_REPORT_ID,
callback: (value) => (conciergeReportID = value),
});
Expand All @@ -297,7 +297,7 @@
// map of reportID to all reportActions for that report
const allReportActions: OnyxCollection<ReportActions> = {};

Onyx.connect({

Check warning on line 300 in src/libs/actions/Report.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.REPORT_ACTIONS,
callback: (actions, key) => {
if (!key || !actions) {
Expand All @@ -309,14 +309,14 @@
});

let allTransactionViolations: OnyxCollection<TransactionViolations> = {};
Onyx.connect({

Check warning on line 312 in src/libs/actions/Report.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.TRANSACTION_VIOLATIONS,
waitForCollectionCallback: true,
callback: (value) => (allTransactionViolations = value),
});

let allReports: OnyxCollection<Report>;
Onyx.connect({

Check warning on line 319 in src/libs/actions/Report.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.COLLECTION.REPORT,
waitForCollectionCallback: true,
callback: (value) => {
Expand All @@ -325,7 +325,7 @@
});

let isNetworkOffline = false;
Onyx.connect({

Check warning on line 328 in src/libs/actions/Report.ts

View workflow job for this annotation

GitHub Actions / Changed files ESLint check

Onyx.connect() is deprecated. Use useOnyx() hook instead and pass the data as parameters to a pure function
key: ONYXKEYS.NETWORK,
callback: (value) => {
isNetworkOffline = value?.isOffline ?? false;
Expand Down Expand Up @@ -3959,6 +3959,13 @@
API.write(WRITE_COMMANDS.INVITE_TO_ROOM, parameters, {optimisticData, successData, failureData});
}

/** Invites people to a room via concierge whisper */
function inviteToRoomAction(reportID: string, ancestors: Ancestor[], inviteeEmailsToAccountIDs: InvitedEmailsToAccountIDs, timezoneParam: Timezone) {
const inviteeEmails = Object.keys(inviteeEmailsToAccountIDs);

addComment(reportID, reportID, ancestors, inviteeEmails.map((login) => `@${login}`).join(' '), timezoneParam, false);
}

function clearAddRoomMemberError(reportID: string, invitedAccountID: string) {
const reportMetadata = getReportMetadata(reportID);
Onyx.merge(`${ONYXKEYS.COLLECTION.REPORT}${reportID}`, {
Expand Down Expand Up @@ -6285,6 +6292,7 @@
inviteToGroupChat,
buildInviteToRoomOnyxData,
inviteToRoom,
inviteToRoomAction,
joinRoom,
leaveGroupChat,
leaveRoom,
Expand Down
24 changes: 18 additions & 6 deletions src/pages/RoomInvitePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@ import InviteMemberListItem from '@components/SelectionListWithSections/InviteMe
import type {Section} from '@components/SelectionListWithSections/types';
import withNavigationTransitionEnd from '@components/withNavigationTransitionEnd';
import type {WithNavigationTransitionEndProps} from '@components/withNavigationTransitionEnd';
import useAncestors from '@hooks/useAncestors';
import useCurrentUserPersonalDetails from '@hooks/useCurrentUserPersonalDetails';
import useDebouncedState from '@hooks/useDebouncedState';
import useLocalize from '@hooks/useLocalize';
import useOnyx from '@hooks/useOnyx';
import useReportIsArchived from '@hooks/useReportIsArchived';
import useThemeStyles from '@hooks/useThemeStyles';
import {inviteToRoom, searchInServer} from '@libs/actions/Report';
import {inviteToRoomAction, searchInServer} from '@libs/actions/Report';
import {clearUserSearchPhrase, updateUserSearchPhrase} from '@libs/actions/RoomMembersUserSearchPhrase';
import {READ_COMMANDS} from '@libs/API/types';
import {canUseTouchScreen} from '@libs/DeviceCapabilities';
Expand Down Expand Up @@ -55,13 +57,14 @@ function RoomInvitePage({
},
}: RoomInvitePageProps) {
const styles = useThemeStyles();
const {translate, formatPhoneNumber} = useLocalize();
const {translate} = useLocalize();
const [userSearchPhrase] = useOnyx(ONYXKEYS.ROOM_MEMBERS_USER_SEARCH_PHRASE, {canBeMissing: true});
const [countryCode = CONST.DEFAULT_COUNTRY_CODE] = useOnyx(ONYXKEYS.COUNTRY_CODE, {canBeMissing: false});
const [searchTerm, debouncedSearchTerm, setSearchTerm] = useDebouncedState(userSearchPhrase ?? '');
const [selectedOptions, setSelectedOptions] = useState<OptionData[]>([]);
const [isSearchingForReports] = useOnyx(ONYXKEYS.IS_SEARCHING_FOR_REPORTS, {initWithStoredValues: false, canBeMissing: true});
const isReportArchived = useReportIsArchived(report.reportID);
const currentUserPersonalDetails = useCurrentUserPersonalDetails();
const [nvpDismissedProductTraining] = useOnyx(ONYXKEYS.NVP_DISMISSED_PRODUCT_TRAINING, {canBeMissing: true});

const {options, areOptionsInitialized} = useOptionsList();
Expand Down Expand Up @@ -191,7 +194,12 @@ function RoomInvitePage({
const backRoute = useMemo(() => {
return reportID && (!isPolicyEmployee || isReportArchived ? ROUTES.REPORT_WITH_ID_DETAILS.getRoute(reportID, backTo) : ROUTES.ROOM_MEMBERS.getRoute(reportID, backTo));
}, [isPolicyEmployee, reportID, backTo, isReportArchived]);

// eslint-disable-next-line @typescript-eslint/no-deprecated
const reportName = useMemo(() => getReportName(report), [report]);

const ancestors = useAncestors(report);

const inviteUsers = useCallback(() => {
HttpUtils.cancelPendingRequests(READ_COMMANDS.SEARCH_FOR_REPORTS);

Expand All @@ -208,11 +216,15 @@ function RoomInvitePage({
invitedEmailsToAccountIDs[login] = Number(accountID);
}
if (reportID) {
inviteToRoom(reportID, invitedEmailsToAccountIDs, formatPhoneNumber);
inviteToRoomAction(reportID, ancestors, invitedEmailsToAccountIDs, currentUserPersonalDetails.timezone ?? CONST.DEFAULT_TIME_ZONE);
clearUserSearchPhrase();
if (backTo) {
Navigation.goBack(backTo);
} else {
Navigation.goBack(ROUTES.REPORT_WITH_ID.getRoute(reportID));
}
}
clearUserSearchPhrase();
Navigation.goBack(backRoute);
}, [selectedOptions, backRoute, reportID, validate, formatPhoneNumber]);
}, [validate, selectedOptions, ancestors, reportID, currentUserPersonalDetails.timezone, backTo]);

const goBack = useCallback(() => {
Navigation.goBack(backRoute);
Expand Down
8 changes: 6 additions & 2 deletions src/pages/home/report/PureReportActionItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ import {isReportMessageAttachment} from '@libs/isReportMessageAttachment';
import Navigation from '@libs/Navigation/Navigation';
import Permissions from '@libs/Permissions';
import {getDisplayNameOrDefault} from '@libs/PersonalDetailsUtils';
import {getCleanedTagName, getPersonalPolicy, isPolicyAdmin, isPolicyOwner} from '@libs/PolicyUtils';
import {getCleanedTagName, getPersonalPolicy, isPolicyAdmin, isPolicyMember, isPolicyOwner} from '@libs/PolicyUtils';
import {
extractLinksFromMessageHtml,
getActionableCardFraudAlertMessage,
Expand Down Expand Up @@ -135,6 +135,7 @@ import {
isResolvedConciergeCategoryOptions,
isResolvedConciergeDescriptionOptions,
isSplitBillAction as isSplitBillActionReportActionsUtils,
isSystemUserMentioned,
isTagModificationAction,
isTaskAction,
isTrackExpenseAction as isTrackExpenseActionReportActionsUtils,
Expand Down Expand Up @@ -939,7 +940,10 @@ function PureReportActionItem({
const actionableMentionWhisperOptions = [];
const isReportInPolicy = !!report?.policyID && report.policyID !== CONST.POLICY.ID_FAKE && getPersonalPolicy()?.id !== report.policyID;

if (isReportInPolicy && (isPolicyAdmin(policy) || isPolicyOwner(policy, currentUserAccountID))) {
// Show the invite to submit expense button even if one of the mentioned users is a not a policy member
const hasMentionedPolicyMembers = getOriginalMessage(action)?.inviteeEmails?.every((login) => isPolicyMember(policy, login)) ?? false;

if ((isPolicyAdmin(policy) || isPolicyOwner(policy, currentUserAccountID)) && isReportInPolicy && !isSystemUserMentioned(action) && !hasMentionedPolicyMembers) {
actionableMentionWhisperOptions.push({
text: 'actionableMentionWhisperOptions.inviteToSubmitExpense',
key: `${action.reportActionID}-actionableMentionWhisper-${CONST.REPORT.ACTIONABLE_MENTION_WHISPER_RESOLUTION.INVITE_TO_SUBMIT_EXPENSE}`,
Expand Down
Loading