Add change subscription to GrReplyDialog

Simplify the rebuildReviewersMethod as well.

Release-Notes: skip
Google-bug-id: b/236921879
Change-Id: I3f2e0ce5b2f6b5f02cda7c436519f271985973bb
diff --git a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.ts b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.ts
index cc4a85f..09850d9 100644
--- a/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.ts
+++ b/polygerrit-ui/app/elements/change/gr-change-view/gr-change-view.ts
@@ -1215,7 +1215,6 @@
           () => html`
             <gr-reply-dialog
               id="replyDialog"
-              .change=${this.change}
               .patchNum=${computeLatestPatchNum(this.allPatchSets)}
               .permittedLabels=${this.change?.permitted_labels}
               .draftCommentThreads=${this.draftCommentThreads}
diff --git a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.ts b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.ts
index ccdcc15..3764e40 100644
--- a/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.ts
+++ b/polygerrit-ui/app/elements/change/gr-reply-dialog/gr-reply-dialog.ts
@@ -33,7 +33,7 @@
 } from '../../../utils/account-util';
 import {IronA11yAnnouncer} from '@polymer/iron-a11y-announcer/iron-a11y-announcer';
 import {TargetElement} from '../../../api/plugin';
-import {FixIronA11yAnnouncer} from '../../../types/types';
+import {FixIronA11yAnnouncer, ParsedChangeInfo} from '../../../types/types';
 import {
   AccountInfoInput,
   AccountInput,
@@ -196,8 +196,9 @@
 
   private readonly getChangeModel = resolve(this, changeModelToken);
 
+  // TODO: update type to only ParsedChangeInfo
   @property({type: Object})
-  change?: ChangeInfo;
+  change?: ParsedChangeInfo | ChangeInfo;
 
   @property({type: String})
   patchNum?: PatchSetNum;
@@ -594,6 +595,13 @@
         this.serverConfig = config;
       }
     );
+    subscribe(
+      this,
+      () => this.getChangeModel().change$,
+      x => {
+        this.change = x;
+      }
+    );
   }
 
   override connectedCallback() {
@@ -649,7 +657,7 @@
     }
     if (changedProperties.has('change')) {
       this.computeUploader();
-      this.changeUpdated();
+      this.rebuildReviewerArrays();
     }
     if (changedProperties.has('canBeStarted')) {
       this.computeMessagePlaceholder();
@@ -1421,7 +1429,7 @@
     return FocusTarget.REVIEWERS;
   }
 
-  isOwner(account?: AccountInfo, change?: ChangeInfo) {
+  isOwner(account?: AccountInfo, change?: ParsedChangeInfo | ChangeInfo) {
     if (!account || !change || !change.owner) return false;
     return account._account_id === change.owner._account_id;
   }
@@ -1479,42 +1487,15 @@
       : 'Say something nice...';
   }
 
-  changeUpdated() {
-    if (this.change === undefined) return;
-    this.rebuildReviewerArrays();
-  }
-
   rebuildReviewerArrays() {
     if (!this.change?.owner || !this.change?.reviewers) return;
+    const getAccounts = (state: ReviewerState) =>
+      Object.values(this.change?.reviewers[state] ?? []).filter(
+        account => account._account_id !== this.change!.owner._account_id
+      );
 
-    const reviewers: AccountInput[] = [];
-    const ccs: AccountInput[] = [];
-
-    if (this.change.reviewers) {
-      for (const key of Object.keys(this.change.reviewers)) {
-        if (key !== 'REVIEWER' && key !== 'CC') {
-          this.reporting.error(new Error(`Unexpected reviewer state: ${key}`));
-          continue;
-        }
-        if (!this.change.reviewers[key]) continue;
-        for (const entry of this.change.reviewers[key]!) {
-          if (entry._account_id === this.change?.owner._account_id) {
-            continue;
-          }
-          switch (key) {
-            case 'REVIEWER':
-              reviewers.push(entry);
-              break;
-            case 'CC':
-              ccs.push(entry);
-              break;
-          }
-        }
-      }
-    }
-
-    this.ccs = ccs;
-    this.reviewers = reviewers;
+    this.ccs = getAccounts(ReviewerState.CC);
+    this.reviewers = getAccounts(ReviewerState.REVIEWER);
   }
 
   handleAttentionModify() {
@@ -2038,7 +2019,7 @@
     this.dispatchEvent(new CustomEvent('send-disabled-changed'));
   }
 
-  getReviewerSuggestionsProvider(change?: ChangeInfo) {
+  getReviewerSuggestionsProvider(change?: ChangeInfo | ParsedChangeInfo) {
     if (!change) return;
     const provider = new GrReviewerSuggestionsProvider(
       this.restApiService,
@@ -2050,7 +2031,7 @@
     return provider;
   }
 
-  getCcSuggestionsProvider(change?: ChangeInfo) {
+  getCcSuggestionsProvider(change?: ChangeInfo | ParsedChangeInfo) {
     if (!change) return;
     const provider = new GrReviewerSuggestionsProvider(
       this.restApiService,
diff --git a/polygerrit-ui/app/scripts/gr-reviewer-suggestions-provider/gr-reviewer-suggestions-provider.ts b/polygerrit-ui/app/scripts/gr-reviewer-suggestions-provider/gr-reviewer-suggestions-provider.ts
index b685522..0bb02d8 100644
--- a/polygerrit-ui/app/scripts/gr-reviewer-suggestions-provider/gr-reviewer-suggestions-provider.ts
+++ b/polygerrit-ui/app/scripts/gr-reviewer-suggestions-provider/gr-reviewer-suggestions-provider.ts
@@ -20,7 +20,7 @@
 import {assertNever} from '../../utils/common-util';
 import {AutocompleteSuggestion} from '../../elements/shared/gr-autocomplete/gr-autocomplete';
 import {allSettled, isFulfilled} from '../../utils/async-util';
-import {notUndefined} from '../../types/types';
+import {notUndefined, ParsedChangeInfo} from '../../types/types';
 import {accountKey} from '../../utils/account-util';
 import {
   AccountId,
@@ -40,14 +40,14 @@
 export class GrReviewerSuggestionsProvider
   implements ReviewerSuggestionsProvider
 {
-  private changes: ChangeInfo[];
+  private changes: (ChangeInfo | ParsedChangeInfo)[];
 
   constructor(
     private restApi: RestApiService,
     private type: ReviewerState.REVIEWER | ReviewerState.CC,
     private config: ServerInfo | undefined,
     private loggedIn: boolean,
-    ...changes: ChangeInfo[]
+    ...changes: (ChangeInfo | ParsedChangeInfo)[]
   ) {
     this.changes = changes;
   }
diff --git a/polygerrit-ui/app/utils/account-util.ts b/polygerrit-ui/app/utils/account-util.ts
index 5967745..8024e81 100644
--- a/polygerrit-ui/app/utils/account-util.ts
+++ b/polygerrit-ui/app/utils/account-util.ts
@@ -22,6 +22,7 @@
 import {getDisplayName} from './display-name-util';
 import {getApprovalInfo} from './label-util';
 import {RestApiService} from '../services/gr-rest-api/gr-rest-api';
+import {ParsedChangeInfo} from '../types/types';
 
 export const ACCOUNT_TEMPLATE_REGEX = '<GERRIT_ACCOUNT_(\\d+)>';
 const SUGGESTIONS_LIMIT = 15;
@@ -60,7 +61,7 @@
 export function isAccountNewlyAdded(
   account: AccountInfo | GroupInfo,
   state?: ReviewerState,
-  change?: ChangeInfo
+  change?: ChangeInfo | ParsedChangeInfo
 ) {
   if (!change || !state) return false;
   const accounts = [...(change.reviewers[state] ?? [])];
diff --git a/polygerrit-ui/app/utils/change-util.ts b/polygerrit-ui/app/utils/change-util.ts
index cf0ff53..78cffce 100644
--- a/polygerrit-ui/app/utils/change-util.ts
+++ b/polygerrit-ui/app/utils/change-util.ts
@@ -250,7 +250,9 @@
   );
 }
 
-export function hasHumanReviewer(change?: ChangeInfo): boolean {
+export function hasHumanReviewer(
+  change?: ChangeInfo | ParsedChangeInfo
+): boolean {
   const reviewers = change?.reviewers.REVIEWER ?? [];
   return reviewers.some(r => !isServiceUser(r));
 }