From d7c33cda282bf39773b605d2397012c9aa7ebc34 Mon Sep 17 00:00:00 2001 From: Bernhard Owen Josephus Date: Wed, 25 Sep 2024 13:32:05 +0800 Subject: [PATCH 1/7] fix assignee regex can't accept multiple domains --- src/pages/home/report/ReportFooter.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/pages/home/report/ReportFooter.tsx b/src/pages/home/report/ReportFooter.tsx index 2bf744868a9a..f91c4ce725a4 100644 --- a/src/pages/home/report/ReportFooter.tsx +++ b/src/pages/home/report/ReportFooter.tsx @@ -129,13 +129,14 @@ function ReportFooter({ * Group 2: Optional email group between \s+....\s* start rule with @+valid email or short mention * Group 3: Title is remaining characters */ - const taskRegex = /^\[\]\s+(?:@([^\s@]+(?:@\w+\.\w+)?))?\s*([\s\S]*)/; + const emailWithOptionalDomainRegex = /(?=((?=[\w'#%+-]+(?:\.[\w'#%+-]+)*@?)[\w\.'#%+-]{1,64}(?:@(?:(?=[a-z\d]+(?:-+[a-z\d]+)*\.)(?:[a-z\d-]{1,63}\.)+[a-z]{2,63}))?(?= |_|\b))(?.*))\S{3,254}(?=\k$)/ + const taskRegex = `^\\[\\]\\s+(?:@(?:${emailWithOptionalDomainRegex.source}))?\\s*([\\s\\S]*)`; const match = text.match(taskRegex); if (!match) { return false; } - const title = match[2] ? match[2].trim().replace(/\n/g, ' ') : undefined; + const title = match[3] ? match[3].trim().replace(/\n/g, ' ') : undefined; if (!title) { return false; } From 6f7ab10a561841ce0383489eaaf757e511af1871 Mon Sep 17 00:00:00 2001 From: Bernhard Owen Josephus Date: Wed, 25 Sep 2024 13:53:29 +0800 Subject: [PATCH 2/7] prettier --- src/pages/home/report/ReportFooter.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/pages/home/report/ReportFooter.tsx b/src/pages/home/report/ReportFooter.tsx index f91c4ce725a4..83c5bf59ae7e 100644 --- a/src/pages/home/report/ReportFooter.tsx +++ b/src/pages/home/report/ReportFooter.tsx @@ -129,7 +129,8 @@ function ReportFooter({ * Group 2: Optional email group between \s+....\s* start rule with @+valid email or short mention * Group 3: Title is remaining characters */ - const emailWithOptionalDomainRegex = /(?=((?=[\w'#%+-]+(?:\.[\w'#%+-]+)*@?)[\w\.'#%+-]{1,64}(?:@(?:(?=[a-z\d]+(?:-+[a-z\d]+)*\.)(?:[a-z\d-]{1,63}\.)+[a-z]{2,63}))?(?= |_|\b))(?.*))\S{3,254}(?=\k$)/ + const emailWithOptionalDomainRegex = + /(?=((?=[\w'#%+-]+(?:\.[\w'#%+-]+)*@?)[\w\.'#%+-]{1,64}(?:@(?:(?=[a-z\d]+(?:-+[a-z\d]+)*\.)(?:[a-z\d-]{1,63}\.)+[a-z]{2,63}))?(?= |_|\b))(?.*))\S{3,254}(?=\k$)/; const taskRegex = `^\\[\\]\\s+(?:@(?:${emailWithOptionalDomainRegex.source}))?\\s*([\\s\\S]*)`; const match = text.match(taskRegex); From fb32c16bb3c03ce04e5dc17255eb4d4ff103d05f Mon Sep 17 00:00:00 2001 From: Bernhard Owen Josephus Date: Wed, 25 Sep 2024 13:55:32 +0800 Subject: [PATCH 3/7] remove unnecessary escape character --- src/pages/home/report/ReportFooter.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/home/report/ReportFooter.tsx b/src/pages/home/report/ReportFooter.tsx index 83c5bf59ae7e..79728909001d 100644 --- a/src/pages/home/report/ReportFooter.tsx +++ b/src/pages/home/report/ReportFooter.tsx @@ -130,7 +130,7 @@ function ReportFooter({ * Group 3: Title is remaining characters */ const emailWithOptionalDomainRegex = - /(?=((?=[\w'#%+-]+(?:\.[\w'#%+-]+)*@?)[\w\.'#%+-]{1,64}(?:@(?:(?=[a-z\d]+(?:-+[a-z\d]+)*\.)(?:[a-z\d-]{1,63}\.)+[a-z]{2,63}))?(?= |_|\b))(?.*))\S{3,254}(?=\k$)/; + /(?=((?=[\w'#%+-]+(?:\.[\w'#%+-]+)*@?)[\w.'#%+-]{1,64}(?:@(?:(?=[a-z\d]+(?:-+[a-z\d]+)*\.)(?:[a-z\d-]{1,63}\.)+[a-z]{2,63}))?(?= |_|\b))(?.*))\S{3,254}(?=\k$)/; const taskRegex = `^\\[\\]\\s+(?:@(?:${emailWithOptionalDomainRegex.source}))?\\s*([\\s\\S]*)`; const match = text.match(taskRegex); From 5e39907b7145a44f5ecd7966330e9d67f9318f8d Mon Sep 17 00:00:00 2001 From: Bernhard Owen Josephus Date: Fri, 27 Sep 2024 16:23:16 +0800 Subject: [PATCH 4/7] prevent creating task with an invalid assignee --- src/pages/home/report/ReportFooter.tsx | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/pages/home/report/ReportFooter.tsx b/src/pages/home/report/ReportFooter.tsx index 79728909001d..d466cb7ffac6 100644 --- a/src/pages/home/report/ReportFooter.tsx +++ b/src/pages/home/report/ReportFooter.tsx @@ -1,3 +1,4 @@ +import {Str} from 'expensify-common'; import lodashIsEqual from 'lodash/isEqual'; import React, {memo, useCallback} from 'react'; import {Keyboard, View} from 'react-native'; @@ -137,17 +138,18 @@ function ReportFooter({ if (!match) { return false; } - const title = match[3] ? match[3].trim().replace(/\n/g, ' ') : undefined; + let title = match[3] ? match[3].trim().replace(/\n/g, ' ') : undefined; if (!title) { return false; } const mention = match[1] ? match[1].trim() : undefined; - const mentionWithDomain = ReportUtils.addDomainToShortMention(mention ?? '') ?? mention; + const mentionWithDomain = ReportUtils.addDomainToShortMention(mention ?? '') ?? mention ?? ''; + const isValidMention = Str.isValidEmail(mentionWithDomain); let assignee: OnyxEntry; let assigneeChatReport; - if (mentionWithDomain) { + if (isValidMention) { assignee = Object.values(allPersonalDetails).find((value) => value?.login === mentionWithDomain) ?? undefined; if (!Object.keys(assignee ?? {}).length) { const assigneeAccountID = UserUtils.generateAccountID(mentionWithDomain); @@ -155,6 +157,10 @@ function ReportFooter({ assignee = optimisticDataForNewAssignee.assignee; assigneeChatReport = optimisticDataForNewAssignee.assigneeReport; } + } else { + // If the mention is not valid, include it on the title. + // The mention could be invalid if it's a short mention and failed to be converted to a full mention. + title = `@${mentionWithDomain} ${title}`; } Task.createTaskAndNavigate(report.reportID, title, '', assignee?.login ?? '', assignee?.accountID, assigneeChatReport, report.policyID); return true; From 6e0410f4aaaa848993141e3399572cbce2f9108b Mon Sep 17 00:00:00 2001 From: Bernhard Owen Josephus Date: Sat, 28 Sep 2024 12:07:29 +0800 Subject: [PATCH 5/7] add the default value early --- src/pages/home/report/ReportFooter.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/home/report/ReportFooter.tsx b/src/pages/home/report/ReportFooter.tsx index d466cb7ffac6..0c989f08437c 100644 --- a/src/pages/home/report/ReportFooter.tsx +++ b/src/pages/home/report/ReportFooter.tsx @@ -143,8 +143,8 @@ function ReportFooter({ return false; } - const mention = match[1] ? match[1].trim() : undefined; - const mentionWithDomain = ReportUtils.addDomainToShortMention(mention ?? '') ?? mention ?? ''; + const mention = match[1] ? match[1].trim() : ''; + const mentionWithDomain = ReportUtils.addDomainToShortMention(mention) ?? mention; const isValidMention = Str.isValidEmail(mentionWithDomain); let assignee: OnyxEntry; From 70e390df66dca8d0ebcfb1530545da95d00cce2f Mon Sep 17 00:00:00 2001 From: Bernhard Owen Josephus Date: Sat, 28 Sep 2024 12:08:08 +0800 Subject: [PATCH 6/7] only add the invalid mention as title if it's not empty --- src/pages/home/report/ReportFooter.tsx | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/pages/home/report/ReportFooter.tsx b/src/pages/home/report/ReportFooter.tsx index 0c989f08437c..bb028b35ad48 100644 --- a/src/pages/home/report/ReportFooter.tsx +++ b/src/pages/home/report/ReportFooter.tsx @@ -149,18 +149,20 @@ function ReportFooter({ let assignee: OnyxEntry; let assigneeChatReport; - if (isValidMention) { - assignee = Object.values(allPersonalDetails).find((value) => value?.login === mentionWithDomain) ?? undefined; - if (!Object.keys(assignee ?? {}).length) { - const assigneeAccountID = UserUtils.generateAccountID(mentionWithDomain); - const optimisticDataForNewAssignee = Task.setNewOptimisticAssignee(mentionWithDomain, assigneeAccountID); - assignee = optimisticDataForNewAssignee.assignee; - assigneeChatReport = optimisticDataForNewAssignee.assigneeReport; + if (mentionWithDomain) { + if (isValidMention) { + assignee = Object.values(allPersonalDetails).find((value) => value?.login === mentionWithDomain) ?? undefined; + if (!Object.keys(assignee ?? {}).length) { + const assigneeAccountID = UserUtils.generateAccountID(mentionWithDomain); + const optimisticDataForNewAssignee = Task.setNewOptimisticAssignee(mentionWithDomain, assigneeAccountID); + assignee = optimisticDataForNewAssignee.assignee; + assigneeChatReport = optimisticDataForNewAssignee.assigneeReport; + } + } else { + // If the mention is not valid, include it on the title. + // The mention could be invalid if it's a short mention and failed to be converted to a full mention. + title = `@${mentionWithDomain} ${title}`; } - } else { - // If the mention is not valid, include it on the title. - // The mention could be invalid if it's a short mention and failed to be converted to a full mention. - title = `@${mentionWithDomain} ${title}`; } Task.createTaskAndNavigate(report.reportID, title, '', assignee?.login ?? '', assignee?.accountID, assigneeChatReport, report.policyID); return true; From 5147c375599bbddaa08fc19055b7ce53acfae350 Mon Sep 17 00:00:00 2001 From: Bernhard Owen Josephus Date: Sat, 28 Sep 2024 12:13:06 +0800 Subject: [PATCH 7/7] add comment --- src/pages/home/report/ReportFooter.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/pages/home/report/ReportFooter.tsx b/src/pages/home/report/ReportFooter.tsx index bb028b35ad48..cea77e8c7bb5 100644 --- a/src/pages/home/report/ReportFooter.tsx +++ b/src/pages/home/report/ReportFooter.tsx @@ -130,6 +130,7 @@ function ReportFooter({ * Group 2: Optional email group between \s+....\s* start rule with @+valid email or short mention * Group 3: Title is remaining characters */ + // The regex is copied from the expensify-common CONST file, but the domain is optional to accept short mention const emailWithOptionalDomainRegex = /(?=((?=[\w'#%+-]+(?:\.[\w'#%+-]+)*@?)[\w.'#%+-]{1,64}(?:@(?:(?=[a-z\d]+(?:-+[a-z\d]+)*\.)(?:[a-z\d-]{1,63}\.)+[a-z]{2,63}))?(?= |_|\b))(?.*))\S{3,254}(?=\k$)/; const taskRegex = `^\\[\\]\\s+(?:@(?:${emailWithOptionalDomainRegex.source}))?\\s*([\\s\\S]*)`;