Merge "Auto resolve comment after applying fix"
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 72a6a3a..721d650 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
@@ -115,7 +115,6 @@
 import {GrFileList} from '../gr-file-list/gr-file-list';
 import {EditRevisionInfo, ParsedChangeInfo} from '../../../types/types';
 import {
-  CloseFixPreviewEvent,
   EditableContentSaveEvent,
   EventType,
   OpenFixPreviewEvent,
@@ -590,8 +589,9 @@
     this.addEventListener('editable-content-cancel', () =>
       this.handleCommitMessageCancel()
     );
-    this.addEventListener('open-fix-preview', e => this.onOpenFixPreview(e));
-    this.addEventListener('close-fix-preview', e => this.onCloseFixPreview(e));
+    this.addEventListener(EventType.OPEN_FIX_PREVIEW, e =>
+      this.onOpenFixPreview(e)
+    );
 
     this.addEventListener(EventType.SHOW_TAB, e => this.setActiveTab(e));
     this.addEventListener('reload', e => {
@@ -1675,10 +1675,6 @@
     this.applyFixDialog.open(e);
   }
 
-  private onCloseFixPreview(e: CloseFixPreviewEvent) {
-    if (e.detail.fixApplied) fireReload(this);
-  }
-
   // Private but used in tests.
   handleToggleDiffMode() {
     if (this.diffViewMode === DiffViewMode.SIDE_BY_SIDE) {
diff --git a/polygerrit-ui/app/elements/diff/gr-apply-fix-dialog/gr-apply-fix-dialog.ts b/polygerrit-ui/app/elements/diff/gr-apply-fix-dialog/gr-apply-fix-dialog.ts
index 5e5d7a9..1608c22 100644
--- a/polygerrit-ui/app/elements/diff/gr-apply-fix-dialog/gr-apply-fix-dialog.ts
+++ b/polygerrit-ui/app/elements/diff/gr-apply-fix-dialog/gr-apply-fix-dialog.ts
@@ -20,7 +20,6 @@
 import {PROVIDED_FIX_ID} from '../../../utils/comment-util';
 import {OpenFixPreviewEvent} from '../../../types/events';
 import {getAppContext} from '../../../services/app-context';
-import {fireCloseFixPreview} from '../../../utils/event-util';
 import {DiffLayer, ParsedChangeInfo} from '../../../types/types';
 import {GrButton} from '../../shared/gr-button/gr-button';
 import {TokenHighlightLayer} from '../../../embed/diff/gr-diff-builder/token-highlight-layer';
@@ -38,6 +37,7 @@
 import {highlightServiceToken} from '../../../services/highlight/highlight-service';
 import {anyLineTooLong} from '../../../embed/diff/gr-diff/gr-diff-utils';
 import {changeModelToken} from '../../../models/change/change-model';
+import {fireReload} from '../../../utils/event-util';
 
 interface FilePreview {
   filepath: string;
@@ -94,6 +94,9 @@
   @state()
   isOwner = false;
 
+  @state()
+  onCloseFixPreviewCallbacks: ((fixapplied: boolean) => void)[] = [];
+
   private readonly restApiService = getAppContext().restApiService;
 
   private readonly getUserModel = resolve(this, userModelToken);
@@ -245,6 +248,7 @@
   open(e: OpenFixPreviewEvent) {
     this.patchNum = e.detail.patchNum;
     this.fixSuggestions = e.detail.fixSuggestions;
+    this.onCloseFixPreviewCallbacks = e.detail.onCloseFixPreviewCallbacks;
     assert(this.fixSuggestions.length > 0, 'no fix in the event');
     this.selectedFixIdx = 0;
     this.applyFixModal?.showModal();
@@ -330,8 +334,9 @@
     this.currentPreviews = [];
     this.isApplyFixLoading = false;
 
-    fireCloseFixPreview(this, fixApplied);
+    this.onCloseFixPreviewCallbacks.forEach(fn => fn(fixApplied));
     this.applyFixModal?.close();
+    if (fixApplied) fireReload(this);
   }
 
   private computeTooltip() {
diff --git a/polygerrit-ui/app/elements/diff/gr-apply-fix-dialog/gr-apply-fix-dialog_test.ts b/polygerrit-ui/app/elements/diff/gr-apply-fix-dialog/gr-apply-fix-dialog_test.ts
index 9a1b488..9284fb2 100644
--- a/polygerrit-ui/app/elements/diff/gr-apply-fix-dialog/gr-apply-fix-dialog_test.ts
+++ b/polygerrit-ui/app/elements/diff/gr-apply-fix-dialog/gr-apply-fix-dialog_test.ts
@@ -17,11 +17,7 @@
 } from '../../../test/test-data-generators';
 import {createDefaultDiffPrefs} from '../../../constants/constants';
 import {DiffInfo} from '../../../types/diff';
-import {
-  CloseFixPreviewEventDetail,
-  EventType,
-  OpenFixPreviewEventDetail,
-} from '../../../types/events';
+import {EventType, OpenFixPreviewEventDetail} from '../../../types/events';
 import {GrButton} from '../../shared/gr-button/gr-button';
 import {fixture, html, assert} from '@open-wc/testing';
 import {SinonStub} from 'sinon';
@@ -37,11 +33,13 @@
       createFixSuggestionInfo('fix_1'),
       createFixSuggestionInfo('fix_2'),
     ],
+    onCloseFixPreviewCallbacks: [],
   };
 
   const ONE_FIX: OpenFixPreviewEventDetail = {
     patchNum: 2 as PatchSetNum,
     fixSuggestions: [createFixSuggestionInfo('fix_1')],
+    onCloseFixPreviewCallbacks: [],
   };
 
   function getConfirmButton(): GrButton {
@@ -261,11 +259,7 @@
     element.currentFix = createFixSuggestionInfo('123');
 
     const closeFixPreviewEventSpy = sinon.spy();
-    // Element is recreated after each test, removeEventListener isn't required
-    element.addEventListener(
-      EventType.CLOSE_FIX_PREVIEW,
-      closeFixPreviewEventSpy
-    );
+    element.onCloseFixPreviewCallbacks.push(closeFixPreviewEventSpy);
 
     await element.handleApplyFix(new CustomEvent('confirm'));
 
@@ -278,14 +272,7 @@
     assert.isTrue(setUrlStub.called);
     assert.equal(setUrlStub.lastCall.firstArg, '/c/test-project/+/42/2..edit');
 
-    sinon.assert.calledOnceWithExactly(
-      closeFixPreviewEventSpy,
-      new CustomEvent<CloseFixPreviewEventDetail>(EventType.CLOSE_FIX_PREVIEW, {
-        detail: {
-          fixApplied: true,
-        },
-      })
-    );
+    sinon.assert.calledOnceWithExactly(closeFixPreviewEventSpy, true);
     // reset gr-apply-fix-dialog and close
     assert.equal(element.currentFix, undefined);
     assert.equal(element.currentPreviews.length, 0);
@@ -326,11 +313,7 @@
     element.currentFix = createFixSuggestionInfo('fix_123');
 
     const closeFixPreviewEventSpy = sinon.spy();
-    // Element is recreated after each test, removeEventListener isn't required
-    element.addEventListener(
-      EventType.CLOSE_FIX_PREVIEW,
-      closeFixPreviewEventSpy
-    );
+    element.onCloseFixPreviewCallbacks.push(closeFixPreviewEventSpy);
 
     let expectedError;
     await element.handleApplyFix(new CustomEvent('click')).catch(e => {
@@ -343,19 +326,8 @@
 
   test('onCancel fires close with correct parameters', () => {
     const closeFixPreviewEventSpy = sinon.spy();
-    // Element is recreated after each test, removeEventListener isn't required
-    element.addEventListener(
-      EventType.CLOSE_FIX_PREVIEW,
-      closeFixPreviewEventSpy
-    );
+    element.onCloseFixPreviewCallbacks.push(closeFixPreviewEventSpy);
     element.onCancel(new CustomEvent('cancel'));
-    sinon.assert.calledOnceWithExactly(
-      closeFixPreviewEventSpy,
-      new CustomEvent<CloseFixPreviewEventDetail>(EventType.CLOSE_FIX_PREVIEW, {
-        detail: {
-          fixApplied: false,
-        },
-      })
-    );
+    sinon.assert.calledOnceWithExactly(closeFixPreviewEventSpy, false);
   });
 });
diff --git a/polygerrit-ui/app/elements/shared/gr-comment/gr-comment.ts b/polygerrit-ui/app/elements/shared/gr-comment/gr-comment.ts
index 1ac89d6..c844d42 100644
--- a/polygerrit-ui/app/elements/shared/gr-comment/gr-comment.ts
+++ b/polygerrit-ui/app/elements/shared/gr-comment/gr-comment.ts
@@ -1053,6 +1053,11 @@
           replacement
         ),
         patchNum: this.comment.patch_set,
+        onCloseFixPreviewCallbacks: [
+          fixApplied => {
+            if (fixApplied) this.handleAppliedFix();
+          },
+        ],
       };
     }
     if (isRobot(this.comment) && this.comment.fix_suggestions.length > 0) {
@@ -1065,6 +1070,7 @@
           };
         }),
         patchNum: this.comment.patch_set,
+        onCloseFixPreviewCallbacks: [],
       };
     }
     throw new Error('unable to create preview fix event');
@@ -1132,6 +1138,18 @@
     fire(this, 'reply-to-comment', eventDetail);
   }
 
+  private handleAppliedFix() {
+    const message = this.comment?.message;
+    assert(!!message, 'empty message');
+    const eventDetail: ReplyToCommentEventDetail = {
+      content: 'Fix applied.',
+      userWantsToEdit: false,
+      unresolved: false,
+    };
+    // Handled by <gr-comment-thread>.
+    fire(this, 'reply-to-comment', eventDetail);
+  }
+
   private async handleShowFix() {
     // Handled top-level in the diff and change view components.
     fire(this, 'open-fix-preview', await this.createFixPreview());
diff --git a/polygerrit-ui/app/models/checks/checks-util.ts b/polygerrit-ui/app/models/checks/checks-util.ts
index ba43eb4..da05bbe 100644
--- a/polygerrit-ui/app/models/checks/checks-util.ts
+++ b/polygerrit-ui/app/models/checks/checks-util.ts
@@ -121,6 +121,7 @@
   const eventDetail: OpenFixPreviewEventDetail = {
     patchNum: result.patchset as PatchSetNumber,
     fixSuggestions,
+    onCloseFixPreviewCallbacks: [],
   };
   return {
     name: 'Show Fix',
diff --git a/polygerrit-ui/app/types/events.ts b/polygerrit-ui/app/types/events.ts
index 2cc6742..e2612b0 100644
--- a/polygerrit-ui/app/types/events.ts
+++ b/polygerrit-ui/app/types/events.ts
@@ -26,7 +26,6 @@
   MOVED_LINK_CLICKED = 'moved-link-clicked',
   NETWORK_ERROR = 'network-error',
   OPEN_FIX_PREVIEW = 'open-fix-preview',
-  CLOSE_FIX_PREVIEW = 'close-fix-preview',
   PAGE_ERROR = 'page-error',
   RELOAD = 'reload',
   REPLY = 'reply',
@@ -63,7 +62,6 @@
     'line-cursor-moved-out': LineNumberEvent;
     'moved-link-clicked': MovedLinkClickedEvent;
     'open-fix-preview': OpenFixPreviewEvent;
-    'close-fix-preview': CloseFixPreviewEvent;
     'reply-to-comment': ReplyToCommentEvent;
     /* prettier-ignore */
     'reload': ReloadEvent;
@@ -156,13 +154,10 @@
 export interface OpenFixPreviewEventDetail {
   patchNum: PatchSetNum;
   fixSuggestions: FixSuggestionInfo[];
+  onCloseFixPreviewCallbacks: ((fixapplied: boolean) => void)[];
 }
 export type OpenFixPreviewEvent = CustomEvent<OpenFixPreviewEventDetail>;
 
-export interface CloseFixPreviewEventDetail {
-  fixApplied: boolean;
-}
-export type CloseFixPreviewEvent = CustomEvent<CloseFixPreviewEventDetail>;
 export interface ReplyToCommentEventDetail {
   content: string;
   userWantsToEdit: boolean;
diff --git a/polygerrit-ui/app/utils/event-util.ts b/polygerrit-ui/app/utils/event-util.ts
index 714955b..49d5382 100644
--- a/polygerrit-ui/app/utils/event-util.ts
+++ b/polygerrit-ui/app/utils/event-util.ts
@@ -103,10 +103,6 @@
   fire(target, EventType.SHOW_TAB, detail);
 }
 
-export function fireCloseFixPreview(target: EventTarget, fixApplied: boolean) {
-  fire(target, EventType.CLOSE_FIX_PREVIEW, {fixApplied});
-}
-
 export function fireReload(target: EventTarget, clearPatchset?: boolean) {
   fire(target, EventType.RELOAD, {clearPatchset: !!clearPatchset});
 }