Merge "Let image diff builder know when to use new UI"
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-element.ts b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-element.ts
index 96ef51a..c51edf3 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-element.ts
+++ b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-element.ts
@@ -140,6 +140,9 @@
   @property({type: Array})
   coverageRanges: CoverageRange[] = [];
 
+  @property({type: Boolean})
+  useNewImageDiffUi = false;
+
   @property({
     type: Array,
     computed: '_computeLeftCoverageRanges(coverageRanges)',
@@ -351,7 +354,8 @@
         this.diffElement,
         this.baseImage,
         this.revisionImage,
-        renderPrefs
+        renderPrefs,
+        this.useNewImageDiffUi
       );
     } else if (diff.binary) {
       // If the diff is binary, but not an image.
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-image.ts b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-image.ts
index fb37349..30b9291 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-image.ts
+++ b/polygerrit-ui/app/elements/diff/gr-diff-builder/gr-diff-builder-image.ts
@@ -20,6 +20,8 @@
 import {DiffInfo, DiffPreferencesInfo} from '../../../types/diff';
 import {GrEndpointParam} from '../../plugins/gr-endpoint-param/gr-endpoint-param';
 import {RenderPreferences} from '../../../api/diff';
+import '../gr-diff-image-viewer/gr-image-viewer';
+import {GrImageViewer} from '../gr-diff-image-viewer/gr-image-viewer';
 
 // MIME types for images we allow showing. Do not include SVG, it can contain
 // arbitrary JavaScript.
@@ -32,7 +34,8 @@
     outputEl: HTMLElement,
     private readonly _baseImage: ImageInfo | null,
     private readonly _revisionImage: ImageInfo | null,
-    renderPrefs?: RenderPreferences
+    renderPrefs?: RenderPreferences,
+    private readonly _useNewImageDiffUi: boolean = false
   ) {
     super(diff, prefs, outputEl, [], renderPrefs);
   }
@@ -40,11 +43,17 @@
   public renderDiff() {
     const section = this._createElement('tbody', 'image-diff');
 
-    this._emitImagePair(section);
-    this._emitImageLabels(section);
+    if (this._useNewImageDiffUi) {
+      this._emitImageViewer(section);
 
-    this._outputEl.appendChild(section);
-    this._outputEl.appendChild(this._createEndpoint());
+      this._outputEl.appendChild(section);
+    } else {
+      this._emitImagePair(section);
+      this._emitImageLabels(section);
+
+      this._outputEl.appendChild(section);
+      this._outputEl.appendChild(this._createEndpoint());
+    }
   }
 
   private _createEndpoint() {
@@ -78,6 +87,27 @@
     return endpointParam;
   }
 
+  private _emitImageViewer(section: HTMLElement) {
+    const tr = this._createElement('tr');
+    const td = this._createElement('td');
+    // TODO(hermannloose): Support blame for image diffs, see above.
+    td.setAttribute('colspan', '4');
+    const imageViewer = this._createElement('gr-image-viewer') as GrImageViewer;
+
+    imageViewer.baseUrl = this._getImageSrc(this._baseImage);
+    imageViewer.revisionUrl = this._getImageSrc(this._revisionImage);
+
+    td.appendChild(imageViewer);
+    tr.appendChild(td);
+    section.appendChild(tr);
+  }
+
+  private _getImageSrc(image: ImageInfo | null): string {
+    return image && IMAGE_MIME_PATTERN.test(image.type)
+      ? `data:${image.type};base64, ${image.body}`
+      : '';
+  }
+
   private _emitImagePair(section: HTMLElement) {
     const tr = this._createElement('tr');
 
@@ -98,18 +128,19 @@
     section: HTMLElement
   ) {
     const td = this._createElement('td', className);
-    if (image && IMAGE_MIME_PATTERN.test(image.type)) {
+    const src = this._getImageSrc(image);
+    if (image && src) {
       const imageEl = this._createElement('img') as HTMLImageElement;
       imageEl.onload = () => {
         image._height = imageEl.naturalHeight;
         image._width = imageEl.naturalWidth;
         this._updateImageLabel(section, className, image);
       };
-      imageEl.setAttribute('src', `data:${image.type};base64, ${image.body}`);
       imageEl.addEventListener('error', (e: Event) => {
         imageEl.remove();
         td.textContent = '[Image failed to load] ' + e.type;
       });
+      imageEl.setAttribute('src', src);
       td.appendChild(imageEl);
     }
     return td;
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host.ts b/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host.ts
index 72131dc..1f4b778 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host.ts
+++ b/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host.ts
@@ -69,6 +69,7 @@
 import {FilesWebLinks} from '../gr-patch-range-select/gr-patch-range-select';
 import {LineNumber, FILE} from '../gr-diff/gr-diff-line';
 import {GrCommentThread} from '../../shared/gr-comment-thread/gr-comment-thread';
+import {KnownExperimentId} from '../../../services/flags/flags';
 import {
   firePageError,
   fireAlert,
@@ -258,6 +259,8 @@
 
   private readonly reporting = appContext.reportingService;
 
+  private readonly flags = appContext.flagsService;
+
   private readonly restApiService = appContext.restApiService;
 
   private readonly jsAPI = appContext.jsApiService;
@@ -1135,6 +1138,10 @@
   _showNewlineWarningRight(diff?: DiffInfo) {
     return this._hasTrailingNewlines(diff, false) === false;
   }
+
+  _useNewImageDiffUi() {
+    return this.flags.isEnabled(KnownExperimentId.NEW_IMAGE_DIFF_UI);
+  }
 }
 
 declare global {
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host_html.ts b/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host_html.ts
index e82489c..3dd2b24 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host_html.ts
+++ b/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host_html.ts
@@ -40,6 +40,7 @@
     diff="[[diff]]"
     show-newline-warning-left="[[_showNewlineWarningLeft(diff)]]"
     show-newline-warning-right="[[_showNewlineWarningRight(diff)]]"
+    use-new-image-diff-ui="[[_useNewImageDiffUi()]]"
   >
   </gr-diff>
 `;
diff --git a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.ts b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.ts
index 39fb554..81be4f5 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.ts
+++ b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.ts
@@ -254,6 +254,9 @@
   @property({type: Boolean})
   showNewlineWarningRight = false;
 
+  @property({type: String})
+  useNewImageDiffUi = false;
+
   @property({
     type: String,
     computed:
diff --git a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff_html.ts b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff_html.ts
index cccee0e..572df0c 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff_html.ts
+++ b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff_html.ts
@@ -100,6 +100,12 @@
     .lineNumButton:focus {
       outline: none;
     }
+    gr-image-viewer {
+      width: 100%;
+      height: 100%;
+      max-width: 95vw;
+      max-height: 90vh;
+    }
     .image-diff .gr-diff {
       text-align: center;
     }
@@ -606,6 +612,7 @@
           base-image="[[baseImage]]"
           layers="[[layers]]"
           revision-image="[[revisionImage]]"
+          use-new-image-diff-ui="[[useNewImageDiffUi]]"
         >
           <table
             id="diffTable"