Skip to content

Commit 095a5c2

Browse files
authored
Merge pull request #40685 from software-mansion-labs/war-in/stop-sending-mention-report-tag
Stop sending <mention-report> when not in a policy room
2 parents b62bbbb + e332742 commit 095a5c2

13 files changed

+62
-33
lines changed

package-lock.json

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@
108108
"date-fns-tz": "^2.0.0",
109109
"dom-serializer": "^0.2.2",
110110
"domhandler": "^4.3.0",
111-
"expensify-common": "git+ssh://[email protected]/Expensify/expensify-common.git#c0f7f3b6558fbeda0527c80d68460d418afef219",
111+
"expensify-common": "git+ssh://[email protected]/Expensify/expensify-common.git#9a68635cdcef4c81593c0f816a007bc9c707d46a",
112112
"expo": "^50.0.3",
113113
"expo-av": "~13.10.4",
114114
"expo-image": "1.11.0",

src/components/ReportActionItem/MoneyRequestView.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ function MoneyRequestView({
164164
const isApprover = ReportUtils.isMoneyRequestReport(moneyRequestReport) && moneyRequestReport?.managerID !== null && session?.accountID === moneyRequestReport?.managerID;
165165
// A flag for verifying that the current report is a sub-report of a workspace chat
166166
// if the policy of the report is either Collect or Control, then this report must be tied to workspace chat
167-
const isPolicyExpenseChat = ReportUtils.isGroupPolicy(report);
167+
const isPolicyExpenseChat = ReportUtils.isReportInGroupPolicy(report);
168168

169169
const policyTagLists = useMemo(() => PolicyUtils.getTagLists(policyTagList), [policyTagList]);
170170

src/hooks/useHandleExceedMaxCommentLength.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
import _ from 'lodash';
22
import {useCallback, useMemo, useState} from 'react';
33
import * as ReportUtils from '@libs/ReportUtils';
4+
import type {ParsingDetails} from '@libs/ReportUtils';
45
import CONST from '@src/CONST';
56

67
const useHandleExceedMaxCommentLength = () => {
78
const [hasExceededMaxCommentLength, setHasExceededMaxCommentLength] = useState(false);
89

910
const handleValueChange = useCallback(
10-
(value: string) => {
11-
if (ReportUtils.getCommentLength(value) <= CONST.MAX_COMMENT_LENGTH) {
11+
(value: string, parsingDetails?: ParsingDetails) => {
12+
if (ReportUtils.getCommentLength(value, parsingDetails) <= CONST.MAX_COMMENT_LENGTH) {
1213
if (hasExceededMaxCommentLength) {
1314
setHasExceededMaxCommentLength(false);
1415
}

src/libs/ReportUtils.ts

Lines changed: 41 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,11 @@ type OutstandingChildRequest = {
474474
hasOutstandingChildRequest?: boolean;
475475
};
476476

477+
type ParsingDetails = {
478+
shouldEscapeText?: boolean;
479+
reportID?: string;
480+
};
481+
477482
let currentUserEmail: string | undefined;
478483
let currentUserPrivateDomain: string | undefined;
479484
let currentUserAccountID: number | undefined;
@@ -881,12 +886,19 @@ function isControlPolicyExpenseChat(report: OnyxEntry<Report>): boolean {
881886
return isPolicyExpenseChat(report) && getPolicyType(report, allPolicies) === CONST.POLICY.TYPE.CORPORATE;
882887
}
883888

889+
/**
890+
* Whether the provided policyType is a Free, Collect or Control policy type
891+
*/
892+
function isGroupPolicy(policyType: string): boolean {
893+
return policyType === CONST.POLICY.TYPE.CORPORATE || policyType === CONST.POLICY.TYPE.TEAM || policyType === CONST.POLICY.TYPE.FREE;
894+
}
895+
884896
/**
885897
* Whether the provided report belongs to a Free, Collect or Control policy
886898
*/
887-
function isGroupPolicy(report: OnyxEntry<Report>): boolean {
899+
function isReportInGroupPolicy(report: OnyxEntry<Report>): boolean {
888900
const policyType = getPolicyType(report, allPolicies);
889-
return policyType === CONST.POLICY.TYPE.CORPORATE || policyType === CONST.POLICY.TYPE.TEAM || policyType === CONST.POLICY.TYPE.FREE;
901+
return isGroupPolicy(policyType);
890902
}
891903

892904
/**
@@ -1454,7 +1466,7 @@ function canAddOrDeleteTransactions(moneyRequestReport: OnyxEntry<Report>): bool
14541466
return false;
14551467
}
14561468

1457-
if (isGroupPolicy(moneyRequestReport) && isProcessingReport(moneyRequestReport) && !PolicyUtils.isInstantSubmitEnabled(getPolicy(moneyRequestReport?.policyID))) {
1469+
if (isReportInGroupPolicy(moneyRequestReport) && isProcessingReport(moneyRequestReport) && !PolicyUtils.isInstantSubmitEnabled(getPolicy(moneyRequestReport?.policyID))) {
14581470
return false;
14591471
}
14601472

@@ -3288,15 +3300,23 @@ function addDomainToShortMention(mention: string): string | undefined {
32883300
* For comments shorter than or equal to 10k chars, convert the comment from MD into HTML because that's how it is stored in the database
32893301
* For longer comments, skip parsing, but still escape the text, and display plaintext for performance reasons. It takes over 40s to parse a 100k long string!!
32903302
*/
3291-
function getParsedComment(text: string, shouldEscapeText?: boolean): string {
3303+
function getParsedComment(text: string, parsingDetails?: ParsingDetails): string {
3304+
let isGroupPolicyReport = false;
3305+
if (parsingDetails?.reportID) {
3306+
const currentReport = getReport(parsingDetails?.reportID);
3307+
isGroupPolicyReport = isReportInGroupPolicy(currentReport);
3308+
}
3309+
32923310
const parser = new ExpensiMark();
32933311
const textWithMention = text.replace(CONST.REGEX.SHORT_MENTION, (match) => {
32943312
const mention = match.substring(1);
32953313
const mentionWithDomain = addDomainToShortMention(mention);
32963314
return mentionWithDomain ? `@${mentionWithDomain}` : match;
32973315
});
32983316

3299-
return text.length <= CONST.MAX_MARKUP_LENGTH ? parser.replace(textWithMention, {shouldEscapeText}) : lodashEscape(text);
3317+
return text.length <= CONST.MAX_MARKUP_LENGTH
3318+
? parser.replace(textWithMention, {shouldEscapeText: parsingDetails?.shouldEscapeText, disabledRules: isGroupPolicyReport ? [] : ['reportMentions']})
3319+
: lodashEscape(text);
33003320
}
33013321

33023322
function getReportDescriptionText(report: Report): string {
@@ -3355,9 +3375,16 @@ function buildOptimisticInviteReportAction(invitedUserDisplayName: string, invit
33553375
};
33563376
}
33573377

3358-
function buildOptimisticAddCommentReportAction(text?: string, file?: FileObject, actorAccountID?: number, createdOffset = 0, shouldEscapeText?: boolean): OptimisticReportAction {
3378+
function buildOptimisticAddCommentReportAction(
3379+
text?: string,
3380+
file?: FileObject,
3381+
actorAccountID?: number,
3382+
createdOffset = 0,
3383+
shouldEscapeText?: boolean,
3384+
reportID?: string,
3385+
): OptimisticReportAction {
33593386
const parser = new ExpensiMark();
3360-
const commentText = getParsedComment(text ?? '', shouldEscapeText);
3387+
const commentText = getParsedComment(text ?? '', {shouldEscapeText, reportID});
33613388
const isAttachmentOnly = file && !text;
33623389
const isTextOnly = text && !file;
33633390

@@ -3479,7 +3506,7 @@ function buildOptimisticTaskCommentReportAction(
34793506
childOldestFourAccountIDs?: string;
34803507
},
34813508
): OptimisticReportAction {
3482-
const reportAction = buildOptimisticAddCommentReportAction(text, undefined, undefined, createdOffset);
3509+
const reportAction = buildOptimisticAddCommentReportAction(text, undefined, undefined, createdOffset, undefined, taskReportID);
34833510
if (reportAction.reportAction.message?.[0]) {
34843511
reportAction.reportAction.message[0].taskReportID = taskReportID;
34853512
}
@@ -5209,8 +5236,8 @@ function getNewMarkerReportActionID(report: OnyxEntry<Report>, sortedAndFiltered
52095236
* Used for compatibility with the backend auth validator for AddComment, and to account for MD in comments
52105237
* @returns The comment's total length as seen from the backend
52115238
*/
5212-
function getCommentLength(textComment: string): number {
5213-
return getParsedComment(textComment)
5239+
function getCommentLength(textComment: string, parsingDetails?: ParsingDetails): number {
5240+
return getParsedComment(textComment, parsingDetails)
52145241
.replace(/[^ -~]/g, '\\u????')
52155242
.trim().length;
52165243
}
@@ -5340,7 +5367,7 @@ function canRequestMoney(report: OnyxEntry<Report>, policy: OnyxEntry<Policy>, o
53405367
// which is tied to their workspace chat.
53415368
if (isMoneyRequestReport(report)) {
53425369
const canAddTransactions = canAddOrDeleteTransactions(report);
5343-
return isGroupPolicy(report) ? isOwnPolicyExpenseChat && canAddTransactions : canAddTransactions;
5370+
return isReportInGroupPolicy(report) ? isOwnPolicyExpenseChat && canAddTransactions : canAddTransactions;
53445371
}
53455372

53465373
// In the case of policy expense chat, users can only submit expenses from their own policy expense chat
@@ -6241,7 +6268,7 @@ function canBeAutoReimbursed(report: OnyxEntry<Report>, policy: OnyxEntry<Policy
62416268
const reimbursableTotal = getMoneyRequestSpendBreakdown(report).totalDisplaySpend;
62426269
const autoReimbursementLimit = policy.autoReimbursementLimit ?? 0;
62436270
const isAutoReimbursable =
6244-
isGroupPolicy(report) &&
6271+
isReportInGroupPolicy(report) &&
62456272
policy.reimbursementChoice === CONST.POLICY.REIMBURSEMENT_CHOICES.REIMBURSEMENT_YES &&
62466273
autoReimbursementLimit >= reimbursableTotal &&
62476274
reimbursableTotal > 0 &&
@@ -6601,7 +6628,7 @@ export {
66016628
isExpensifyOnlyParticipantInReport,
66026629
isGroupChat,
66036630
isGroupChatAdmin,
6604-
isGroupPolicy,
6631+
isReportInGroupPolicy,
66056632
isHoldCreator,
66066633
isIOUOwnedByCurrentUser,
66076634
isIOUReport,
@@ -6688,4 +6715,5 @@ export type {
66886715
OptionData,
66896716
TransactionDetails,
66906717
OptimisticInviteReportAction,
6718+
ParsingDetails,
66916719
};

src/libs/actions/Report.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -450,7 +450,7 @@ function addActions(reportID: string, text = '', file?: FileObject) {
450450
let commandName: typeof WRITE_COMMANDS.ADD_COMMENT | typeof WRITE_COMMANDS.ADD_ATTACHMENT | typeof WRITE_COMMANDS.ADD_TEXT_AND_ATTACHMENT = WRITE_COMMANDS.ADD_COMMENT;
451451

452452
if (text && !file) {
453-
const reportComment = ReportUtils.buildOptimisticAddCommentReportAction(text);
453+
const reportComment = ReportUtils.buildOptimisticAddCommentReportAction(text, undefined, undefined, undefined, undefined, reportID);
454454
reportCommentAction = reportComment.reportAction;
455455
reportCommentText = reportComment.commentText;
456456
}
@@ -459,13 +459,13 @@ function addActions(reportID: string, text = '', file?: FileObject) {
459459
// When we are adding an attachment we will call AddAttachment.
460460
// It supports sending an attachment with an optional comment and AddComment supports adding a single text comment only.
461461
commandName = WRITE_COMMANDS.ADD_ATTACHMENT;
462-
const attachment = ReportUtils.buildOptimisticAddCommentReportAction(text, file);
462+
const attachment = ReportUtils.buildOptimisticAddCommentReportAction(text, file, undefined, undefined, undefined, reportID);
463463
attachmentAction = attachment.reportAction;
464464
}
465465

466466
if (text && file) {
467467
// When there is both text and a file, the text for the report comment needs to be parsed)
468-
reportCommentText = ReportUtils.getParsedComment(text ?? '');
468+
reportCommentText = ReportUtils.getParsedComment(text ?? '', {reportID});
469469

470470
// And the API command needs to go to the new API which supports combining both text and attachments in a single report action
471471
commandName = WRITE_COMMANDS.ADD_TEXT_AND_ATTACHMENT;
@@ -1844,7 +1844,7 @@ function updateDescription(reportID: string, previousValue: string, newValue: st
18441844
return;
18451845
}
18461846

1847-
const parsedDescription = ReportUtils.getParsedComment(newValue);
1847+
const parsedDescription = ReportUtils.getParsedComment(newValue, {reportID});
18481848

18491849
const optimisticData: OnyxUpdate[] = [
18501850
{

src/pages/home/report/ReportActionCompose/ComposerWithSuggestions/ComposerWithSuggestions.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -458,7 +458,7 @@ function ComposerWithSuggestions(
458458

459459
const prepareCommentAndResetComposer = useCallback((): string => {
460460
const trimmedComment = commentRef.current.trim();
461-
const commentLength = ReportUtils.getCommentLength(trimmedComment);
461+
const commentLength = ReportUtils.getCommentLength(trimmedComment, {reportID});
462462

463463
// Don't submit empty comments or comments that exceed the character limit
464464
if (!commentLength || commentLength > CONST.MAX_COMMENT_LENGTH) {

src/pages/home/report/ReportActionCompose/ReportActionCompose.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -461,7 +461,7 @@ function ReportActionCompose({
461461
if (value.length === 0 && isComposerFullSize) {
462462
Report.setIsComposerFullSize(reportID, false);
463463
}
464-
validateCommentMaxLength(value);
464+
validateCommentMaxLength(value, {reportID});
465465
}}
466466
/>
467467
<ReportDropUI

src/pages/home/report/ReportActionItemMessageEdit.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ function ReportActionItemMessageEdit(
318318
*/
319319
const publishDraft = useCallback(() => {
320320
// Do nothing if draft exceed the character limit
321-
if (ReportUtils.getCommentLength(draft) > CONST.MAX_COMMENT_LENGTH) {
321+
if (ReportUtils.getCommentLength(draft, {reportID}) > CONST.MAX_COMMENT_LENGTH) {
322322
return;
323323
}
324324

@@ -380,8 +380,8 @@ function ReportActionItemMessageEdit(
380380
const focus = focusComposerWithDelay(textInputRef.current);
381381

382382
useEffect(() => {
383-
validateCommentMaxLength(draft);
384-
}, [draft, validateCommentMaxLength]);
383+
validateCommentMaxLength(draft, {reportID});
384+
}, [draft, reportID, validateCommentMaxLength]);
385385

386386
return (
387387
<>

src/pages/iou/HoldReasonPage.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ function HoldReasonPage({route}: HoldReasonPageProps) {
4949

5050
// We first check if the report is part of a policy - if not, then it's a personal request (1:1 request)
5151
// For personal requests, we need to allow both users to put the request on hold
52-
const isWorkspaceRequest = ReportUtils.isGroupPolicy(report);
52+
const isWorkspaceRequest = ReportUtils.isReportInGroupPolicy(report);
5353
const parentReportAction = ReportActionsUtils.getReportAction(report?.parentReportID ?? '', report?.parentReportActionID ?? '');
5454

5555
const navigateBack = () => {

src/pages/iou/request/step/IOURequestStepCategory.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ function IOURequestStepCategory({
7373

7474
// The transactionCategory can be an empty string, so to maintain the logic we'd like to keep it in this shape until utils refactor
7575
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
76-
const shouldShowCategory = ReportUtils.isGroupPolicy(report) && (!!transactionCategory || OptionsListUtils.hasEnabledOptions(Object.values(policyCategories ?? {})));
76+
const shouldShowCategory = ReportUtils.isReportInGroupPolicy(report) && (!!transactionCategory || OptionsListUtils.hasEnabledOptions(Object.values(policyCategories ?? {})));
7777

7878
const isSplitBill = iouType === CONST.IOU.TYPE.SPLIT;
7979
const canEditSplitBill = isSplitBill && reportAction && session?.accountID === reportAction.actorAccountID && TransactionUtils.areRequiredFieldsEmpty(transaction);

src/pages/iou/request/step/IOURequestStepMerchant.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ function IOURequestStepMerchant({
6363
const merchant = ReportUtils.getTransactionDetails(isEditingSplitBill && !isEmptyObject(splitDraftTransaction) ? splitDraftTransaction : transaction)?.merchant;
6464
const isEmptyMerchant = merchant === '' || merchant === CONST.TRANSACTION.PARTIAL_TRANSACTION_MERCHANT;
6565

66-
const isMerchantRequired = ReportUtils.isGroupPolicy(report) || transaction?.participants?.some((participant) => Boolean(participant.isPolicyExpenseChat));
66+
const isMerchantRequired = ReportUtils.isReportInGroupPolicy(report) || transaction?.participants?.some((participant) => Boolean(participant.isPolicyExpenseChat));
6767
const navigateBack = () => {
6868
Navigation.goBack(backTo);
6969
};

src/pages/iou/request/step/IOURequestStepTag.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ function IOURequestStepTag({
7777
const canEditSplitBill = isSplitBill && reportAction && session?.accountID === reportAction.actorAccountID && TransactionUtils.areRequiredFieldsEmpty(transaction);
7878
const policyTagLists = useMemo(() => PolicyUtils.getTagLists(policyTags), [policyTags]);
7979

80-
const shouldShowTag = ReportUtils.isGroupPolicy(report) && (transactionTag || OptionsListUtils.hasEnabledTags(policyTagLists));
80+
const shouldShowTag = ReportUtils.isReportInGroupPolicy(report) && (transactionTag || OptionsListUtils.hasEnabledTags(policyTagLists));
8181

8282
// eslint-disable-next-line rulesdir/no-negated-variables
8383
const shouldShowNotFoundPage = !shouldShowTag || (isEditing && (isSplitBill ? !canEditSplitBill : reportAction && !canEditMoneyRequest(reportAction)));

0 commit comments

Comments
 (0)