Merge "Add mentionedUsers$ to comments-model"
diff --git a/polygerrit-ui/app/models/comments/comments-model.ts b/polygerrit-ui/app/models/comments/comments-model.ts
index f0d3be2..daf4d00 100644
--- a/polygerrit-ui/app/models/comments/comments-model.ts
+++ b/polygerrit-ui/app/models/comments/comments-model.ts
@@ -14,6 +14,7 @@
   PathToCommentsInfoMap,
   RobotCommentInfo,
   PathToRobotCommentsInfoMap,
+  AccountInfo,
 } from '../../types/common';
 import {
   addPath,
@@ -34,12 +35,13 @@
 import {RestApiService} from '../../services/gr-rest-api/gr-rest-api';
 import {ChangeModel} from '../change/change-model';
 import {Interaction, Timing} from '../../constants/reporting';
-import {assertIsDefined} from '../../utils/common-util';
+import {assertIsDefined, unique} from '../../utils/common-util';
 import {debounce, DelayedTask} from '../../utils/async-util';
 import {pluralize} from '../../utils/string-util';
 import {ReportingService} from '../../services/gr-reporting/gr-reporting';
 import {Model} from '../model';
 import {Deduping} from '../../api/reporting';
+import {extractMentionedUsers} from '../../utils/account-util';
 
 export interface CommentState {
   /** undefined means 'still loading' */
@@ -251,6 +253,15 @@
     commentState => commentState.discardedDrafts
   );
 
+  public readonly mentionedUsersInDrafts$ = select(this.drafts$, drafts => {
+    const users: AccountInfo[] = [];
+    const comments = Object.values(drafts ?? {}).flat();
+    for (const comment of comments) {
+      users.push(...extractMentionedUsers(comment.message));
+    }
+    return users.filter(unique);
+  });
+
   // Emits a new value even if only a single draft is changed. Components should
   // aim to subsribe to something more specific.
   public readonly changeComments$ = select(
diff --git a/polygerrit-ui/app/utils/account-util.ts b/polygerrit-ui/app/utils/account-util.ts
index 012dc1c..5967745 100644
--- a/polygerrit-ui/app/utils/account-util.ts
+++ b/polygerrit-ui/app/utils/account-util.ts
@@ -199,14 +199,16 @@
  * @ token which would have triggered the mentions dropdown and then looks
  * for the email token ending with a whitespace or end of string.
  */
-export function extractMentionedEmails(text?: string): EmailAddress[] {
+export function extractMentionedUsers(text?: string): AccountInfo[] {
   if (!text) return [];
   let match;
-  const emails = [];
+  const users = [];
   while ((match = MENTIONS_REGEX.exec(text))) {
-    emails.push(match[1] as EmailAddress);
+    users.push({
+      email: match[1] as EmailAddress,
+    });
   }
-  return emails;
+  return users;
 }
 
 export function toReviewInput(
diff --git a/polygerrit-ui/app/utils/account-util_test.ts b/polygerrit-ui/app/utils/account-util_test.ts
index 68fa386..c4f4701 100644
--- a/polygerrit-ui/app/utils/account-util_test.ts
+++ b/polygerrit-ui/app/utils/account-util_test.ts
@@ -6,7 +6,7 @@
 import '../test/common-test-setup-karma';
 import {
   computeVoteableText,
-  extractMentionedEmails,
+  extractMentionedUsers,
   getAccountTemplate,
   isServiceUser,
   removeServiceUsers,
@@ -17,7 +17,12 @@
   AccountTag,
   DefaultDisplayNameConfig,
 } from '../constants/constants';
-import {AccountId, AccountInfo, ServerInfo} from '../api/rest-api';
+import {
+  AccountId,
+  AccountInfo,
+  EmailAddress,
+  ServerInfo,
+} from '../api/rest-api';
 import {
   createAccountDetailWithId,
   createChange,
@@ -61,35 +66,41 @@
     assert.isTrue(isServiceUser(BOTTY));
   });
 
-  test('extractMentionedEmails', () => {
+  test('extractMentionedUsers', () => {
     let text =
       'Hi @kamilm@google.com and @brohlfs@google.com can you take a look at this?';
-    assert.deepEqual(extractMentionedEmails(text), [
-      'kamilm@google.com',
-      'brohlfs@google.com',
+    assert.deepEqual(extractMentionedUsers(text), [
+      {email: 'kamilm@google.com' as EmailAddress},
+      {email: 'brohlfs@google.com' as EmailAddress},
     ]);
 
     // with extra @
     text = '@@abc@google.com';
-    assert.deepEqual(extractMentionedEmails(text), []);
+    assert.deepEqual(extractMentionedUsers(text), []);
 
     // with spaces in email
     text = '@a bc@google.com';
-    assert.deepEqual(extractMentionedEmails(text), []);
+    assert.deepEqual(extractMentionedUsers(text), []);
 
     // with invalid email
     text = '@abcgoogle.com';
-    assert.deepEqual(extractMentionedEmails(text), []);
+    assert.deepEqual(extractMentionedUsers(text), []);
 
     text = '@abc@googlecom';
-    assert.deepEqual(extractMentionedEmails(text), ['abc@googlecom']);
+    assert.deepEqual(extractMentionedUsers(text), [
+      {email: 'abc@googlecom' as EmailAddress},
+    ]);
 
     // with newline before email
     text = '\n\n\n random text  \n\n@abc@google.com';
-    assert.deepEqual(extractMentionedEmails(text), ['abc@google.com']);
+    assert.deepEqual(extractMentionedUsers(text), [
+      {email: 'abc@google.com' as EmailAddress},
+    ]);
 
     text = '@abc@google.com please take a look at this';
-    assert.deepEqual(extractMentionedEmails(text), ['abc@google.com']);
+    assert.deepEqual(extractMentionedUsers(text), [
+      {email: 'abc@google.com' as EmailAddress},
+    ]);
   });
 
   test('removeServiceUsers', () => {