Add header to diff

Adds the header section to the diff. The header is only displayed when
relevant information is contained within, e.g. when a file is renamed
but otherwise left unchanged.

Feature: Issue 5752
Change-Id: I5f8cb56522decd8d3c57bb403cb43f87203d5c6a
diff --git a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.html b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.html
index 54e9c6e..1bf6268 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.html
@@ -173,8 +173,22 @@
         border-radius: .4em;
         background-color: #FF9AD2;
       }
+      #diffHeader {
+        background-color: #F9F9F9;
+        color: #2A00FF;
+        font-family: var(--monospace-font-family);
+        font-size: var(--font-size, 12px);
+        padding: 0.5em 0 0.5em 4em;
+      }
     </style>
     <style include="gr-theme-default"></style>
+    <div id="diffHeader" hidden$="[[_computeDiffHeaderHidden(_diffHeaderItems)]]">
+      <template
+          is="dom-repeat"
+          items="[[_diffHeaderItems]]">
+        <div>[[item]]</div>
+      </template>
+    </div>
     <div class$="[[_computeContainerClass(_loggedIn, viewMode, displayLine)]]"
         on-tap="_handleTap">
       <gr-diff-selection diff="[[_diff]]">
diff --git a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.js b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.js
index 52e869f..155ed5a 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.js
@@ -89,6 +89,11 @@
         observer: '_viewModeObserver',
       },
       _diff: Object,
+      _diffHeaderItems: {
+        type: Array,
+        value: [],
+        computed: '_computeDiffHeaderItems(_diff.*)',
+      },
       _diffTableClass: {
         type: String,
         value: '',
@@ -336,7 +341,7 @@
       this._removeComment(comment, e.detail.patchNum);
     },
 
-    _removeComment: function(comment, opt_patchNum) {
+    _removeComment: function(comment) {
       var side = comment.__commentSide;
       this._removeCommentFromSide(comment, side);
     },
@@ -576,5 +581,20 @@
         threadEls[i].projectConfig = projectConfig;
       }
     },
+
+    _computeDiffHeaderItems: function(diffInfoRecord) {
+      var diffInfo = diffInfoRecord.base;
+      if (!diffInfo || !diffInfo.diff_header || diffInfo.binary) { return []; }
+      return diffInfo.diff_header.filter(function(item) {
+        return !(item.indexOf('diff --git ') === 0 ||
+            item.indexOf('index ') === 0 ||
+            item.indexOf('+++ ') === 0 ||
+            item.indexOf('--- ') === 0);
+      });
+    },
+
+    _computeDiffHeaderHidden: function(items) {
+      return items.length === 0;
+    },
   });
 })();
diff --git a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff_test.html b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff_test.html
index ad7a260..340adf7 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff_test.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff_test.html
@@ -776,5 +776,38 @@
         });
       });
     });
+
+    suite('diff header', function() {
+      setup(function() {
+        element._diff = {
+            meta_a: {name: 'carrot.jpg', content_type: 'image/jpeg', lines: 66},
+            meta_b: {name: 'carrot.jpg', content_type: 'image/jpeg',
+                lines: 560},
+            diff_header: [],
+            intraline_status: 'OK',
+            change_type: 'MODIFIED',
+            content: [{skip: 66}],
+          };
+      });
+
+      test('hidden', function() {
+        assert.equal(element._diffHeaderItems.length, 0);
+        element.push('_diff.diff_header', 'diff --git a/test.jpg b/test.jpg');
+        assert.equal(element._diffHeaderItems.length, 0);
+        element.push('_diff.diff_header', 'index 2adc47d..f9c2f2c 100644');
+        assert.equal(element._diffHeaderItems.length, 0);
+        element.push('_diff.diff_header', '--- a/test.jpg');
+        assert.equal(element._diffHeaderItems.length, 0);
+        element.push('_diff.diff_header', '+++ b/test.jpg');
+        assert.equal(element._diffHeaderItems.length, 0);
+        element.push('_diff.diff_header', 'test');
+        assert.equal(element._diffHeaderItems.length, 1);
+        flushAsynchronousOperations();
+
+        assert.equal(element.$.diffHeader.textContent.trim(), 'test');
+        element.set('_diff.binary', true);
+        assert.equal(element._diffHeaderItems.length, 0);
+      });
+    });
   });
 </script>