Update the URL hash with the selected diff line
Sets the URL hash to the address of the cursor when a user selects a
diff line (either by clicking the line number or using the 'c' hotkey).
If the cursor is on a line of the revision, the address is the line
number. If the cursor is on a line of the base patch, the address is the
letter 'b' followed by the line number. Otherwise the address is the
empty string.
Bug: Issue 4206
Change-Id: Ic85da197eb6264ea1111cc34e781dccbc24d4d40
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-cursor/gr-diff-cursor.js b/polygerrit-ui/app/elements/diff/gr-diff-cursor/gr-diff-cursor.js
index f3d00a7..a730a68 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-cursor/gr-diff-cursor.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff-cursor/gr-diff-cursor.js
@@ -115,6 +115,14 @@
this._fixSide();
},
+ moveToLineNumber: function(number, side) {
+ var row = this._findRowByNumber(number, side);
+ if (row) {
+ this.side = side;
+ this.$.cursorManager.setCursor(row);
+ }
+ },
+
/**
* Get the line number element targeted by the cursor row and side.
* @return {DOMElement}
@@ -159,6 +167,34 @@
}
},
+ /**
+ * Get a short address for the location of the cursor. Such as '123' for
+ * line 123 of the revision, or 'b321' for line 321 of the base patch.
+ * Returns an empty string if an address is not available.
+ * @return {String}
+ */
+ getAddress: function() {
+ if (!this.diffRow) { return ''; }
+
+ // Get the line-number cell targeted by the cursor. If the mode is unified
+ // then prefer the revision cell if available.
+ var cell;
+ if (this._getViewMode() === DiffViewMode.UNIFIED) {
+ cell = this.diffRow.querySelector('.lineNum.right');
+ if (!cell) {
+ cell = this.diffRow.querySelector('.lineNum.left');
+ }
+ } else {
+ cell = this.diffRow.querySelector('.lineNum.' + this.side);
+ }
+ if (!cell) { return ''; }
+
+ var number = cell.getAttribute('data-value');
+ if (!number || number === 'FILE') { return ''; }
+
+ return (cell.matches('.left') ? 'b' : '') + number;
+ },
+
_getViewMode: function() {
if (!this.diffRow) {
return null;
@@ -284,5 +320,16 @@
}
}
},
+
+ _findRowByNumber: function(targetNumber, side) {
+ var stops = this.$.cursorManager.stops;
+ var selector;
+ for (var i = 0; i < stops.length; i++) {
+ selector = '.lineNum.' + side + '[data-value="' + targetNumber + '"]';
+ if (stops[i].querySelector(selector)) {
+ return stops[i];
+ }
+ }
+ },
});
})();
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-cursor/gr-diff-cursor_test.html b/polygerrit-ui/app/elements/diff/gr-diff-cursor/gr-diff-cursor_test.html
index 4dbabf7..e3d7e46 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-cursor/gr-diff-cursor_test.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff-cursor/gr-diff-cursor_test.html
@@ -181,5 +181,39 @@
assert.equal(currentIndex, previousIndex + 1);
assert.equal(cursorElement.side, 'left');
});
+
+ test('getAddress', function() {
+ // It should initialize to the first chunk: line 5 of the revision.
+ assert.equal(cursorElement.getAddress(), '5');
+
+ // Revision line 4 is up.
+ cursorElement.moveUp();
+ assert.equal(cursorElement.getAddress(), '4');
+
+ // Base line 4 is left.
+ cursorElement.moveLeft();
+ assert.equal(cursorElement.getAddress(), 'b4');
+
+ // Moving to the next chunk takes it back to the start.
+ cursorElement.moveToNextChunk();
+ assert.equal(cursorElement.getAddress(), '5');
+
+ // The following chunk is a removal starting on line 10 of the base.
+ cursorElement.moveToNextChunk();
+ assert.equal(cursorElement.getAddress(), 'b10');
+
+ // Should be an empty string if there is no selection.
+ cursorElement.$.cursorManager.unsetCursor();
+ assert.equal(cursorElement.getAddress(), '');
+ });
+
+ test('_findRowByNumber', function() {
+ // Get the first ab row after the first chunk.
+ var row = Polymer.dom(diffElement.root).querySelectorAll('tr')[8];
+
+ // It should be line 8 on the right, but line 5 on the left.
+ assert.equal(cursorElement._findRowByNumber(8, 'right'), row);
+ assert.equal(cursorElement._findRowByNumber(5, 'left'), row);
+ });
});
</script>
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.html b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.html
index 943b24b..0e9db86 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.html
+++ b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.html
@@ -210,7 +210,7 @@
has-ranged-comments="[[_localPrefs.ranged_comments]]"
project-config="[[_projectConfig]]"
view-mode="[[_diffMode]]"
- on-render="_handleDiffRender">
+ on-line-selected="_onLineSelected">
</gr-diff>
</div>
<gr-rest-api-interface id="restAPI"></gr-rest-api-interface>
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.js b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.js
index e3f0c0c..afc51cd 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.js
@@ -457,5 +457,10 @@
_computeModeSelectHidden: function() {
return this._isImageDiff;
},
+
+ _onLineSelected: function(e, detail) {
+ this.$.cursor.moveToLineNumber(detail.number, detail.side);
+ history.pushState(null, null, '#' + this.$.cursor.getAddress());
+ },
});
})();
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 cf9e6d4..7c64908 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff/gr-diff.js
@@ -27,6 +27,11 @@
Polymer({
is: 'gr-diff',
+ /**
+ * Fired when the user selects a line.
+ * @event line-selected
+ */
+
properties: {
changeNum: String,
patchRange: Object,
@@ -118,6 +123,7 @@
},
addDraftAtLine: function(el) {
+ this._selectLine(el);
this._getLoggedIn().then(function(loggedIn) {
if (!loggedIn) { return; }
@@ -198,6 +204,13 @@
}
},
+ _selectLine: function(el) {
+ this.fire('line-selected', {
+ side: el.classList.contains('left') ? DiffSide.LEFT : DiffSide.RIGHT,
+ number: el.getAttribute('data-value'),
+ });
+ },
+
_handleCreateComment: function(e) {
var range = e.detail.range;
var diffSide = e.detail.side;