summaryrefslogtreecommitdiffstats
path: root/polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.js
diff options
context:
space:
mode:
Diffstat (limited to 'polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.js')
-rw-r--r--polygerrit-ui/app/elements/diff/gr-diff-view/gr-diff-view.js628
1 files changed, 368 insertions, 260 deletions
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 d1ac8426bd..b97d974520 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
@@ -14,18 +14,17 @@
(function() {
'use strict';
- var COMMIT_MESSAGE_PATH = '/COMMIT_MSG';
- var MERGE_LIST_PATH = '/MERGE_LIST';
+ const ERR_REVIEW_STATUS = 'Couldn’t change file review status.';
+ const MSG_LOADING_BLAME = 'Loading blame...';
+ const MSG_LOADED_BLAME = 'Blame loaded';
- var COMMENT_SAVE = 'Try again when all comments have saved.';
+ const PARENT = 'PARENT';
- var DiffSides = {
+ const DiffSides = {
LEFT: 'left',
RIGHT: 'right',
};
- var HASH_PATTERN = /^[ab]?\d+$/;
-
Polymer({
is: 'gr-diff-view',
@@ -51,21 +50,32 @@
},
keyEventTarget: {
type: Object,
- value: function() { return document.body; },
+ value() { return document.body; },
},
+ /**
+ * @type {{ diffMode: (string|undefined) }}
+ */
changeViewState: {
type: Object,
notify: true,
- value: function() { return {}; },
+ value() { return {}; },
+ observer: '_changeViewStateChanged',
},
-
+ /** @type {?} */
_patchRange: Object,
+ /**
+ * @type {{
+ * subject: string,
+ * project: string,
+ * revisions: string,
+ * }}
+ */
_change: Object,
_changeNum: String,
_diff: Object,
_fileList: {
type: Array,
- value: function() { return []; },
+ value() { return []; },
},
_path: {
type: String,
@@ -96,6 +106,8 @@
*/
_commentMap: Object,
+ _commentsForDiff: Object,
+
/**
* Object to contain the path of the next and previous file in the current
* change and patch range that has comments.
@@ -104,18 +116,40 @@
type: Object,
computed: '_computeCommentSkips(_commentMap, _fileList, _path)',
},
+ _panelFloatingDisabled: {
+ type: Boolean,
+ value: () => { return window.PANEL_FLOATING_DISABLED; },
+ },
+ _editLoaded: {
+ type: Boolean,
+ computed: '_computeEditLoaded(_patchRange.*)',
+ },
+ _isBlameSupported: {
+ type: Boolean,
+ value: false,
+ },
+ _isBlameLoaded: Boolean,
+ _isBlameLoading: {
+ type: Boolean,
+ value: false,
+ },
+ _allPatchSets: {
+ type: Array,
+ computed: 'computeAllPatchSets(_change, _change.revisions.*)',
+ },
},
behaviors: [
- Gerrit.BaseUrlBehavior,
Gerrit.KeyboardShortcutBehavior,
+ Gerrit.PatchSetBehavior,
+ Gerrit.PathListBehavior,
Gerrit.RESTClientBehavior,
- Gerrit.URLEncodingBehavior,
],
observers: [
'_getProjectConfig(_change.project)',
'_getFiles(_changeNum, _patchRange.*)',
+ '_setReviewedObserver(_loggedIn, params.*)',
],
keyBindings: {
@@ -134,85 +168,78 @@
',': '_handleCommaKey',
},
- attached: function() {
- this._getLoggedIn().then(function(loggedIn) {
+ attached() {
+ this._getLoggedIn().then(loggedIn => {
this._loggedIn = loggedIn;
- if (loggedIn) {
- this._setReviewed(true);
- }
- }.bind(this));
- if (this.changeViewState.diffMode === null) {
- // If screen size is small, always default to unified view.
- this.$.restAPI.getPreferences().then(function(prefs) {
- this.set('changeViewState.diffMode', prefs.default_diff_view);
- }.bind(this));
- }
+ });
- if (this._path) {
- this.fire('title-change',
- {title: this._computeFileDisplayName(this._path)});
- }
+ this.$.restAPI.getConfig().then(config => {
+ this._isBlameSupported = config.change.allow_blame;
+ });
this.$.cursor.push('diffs', this.$.diff);
},
- _getLoggedIn: function() {
+ _getLoggedIn() {
return this.$.restAPI.getLoggedIn();
},
- _getProjectConfig: function(project) {
+ _getProjectConfig(project) {
return this.$.restAPI.getProjectConfig(project).then(
- function(config) {
+ config => {
this._projectConfig = config;
- }.bind(this));
+ });
+ },
+
+ _getChangeDetail(changeNum) {
+ return this.$.restAPI.getDiffChangeDetail(changeNum).then(change => {
+ this._change = change;
+ });
},
- _getChangeDetail: function(changeNum) {
- return this.$.restAPI.getDiffChangeDetail(changeNum).then(
- function(change) {
- this._change = change;
- }.bind(this));
+ _getChangeEdit(changeNum) {
+ return this.$.restAPI.getChangeEdit(this._changeNum);
},
- _getFiles: function(changeNum, patchRangeRecord) {
- var patchRange = patchRangeRecord.base;
+ _getFiles(changeNum, patchRangeRecord) {
+ const patchRange = patchRangeRecord.base;
return this.$.restAPI.getChangeFilePathsAsSpeciallySortedArray(
- changeNum, patchRange).then(function(files) {
+ changeNum, patchRange).then(files => {
this._fileList = files;
- }.bind(this));
+ });
},
- _getDiffPreferences: function() {
+ _getDiffPreferences() {
return this.$.restAPI.getDiffPreferences();
},
- _getPreferences: function() {
+ _getPreferences() {
return this.$.restAPI.getPreferences();
},
- _getWindowWidth: function() {
+ _getWindowWidth() {
return window.innerWidth;
},
- _handleReviewedChange: function(e) {
+ _handleReviewedChange(e) {
this._setReviewed(Polymer.dom(e).rootTarget.checked);
},
- _setReviewed: function(reviewed) {
+ _setReviewed(reviewed) {
+ if (this._editLoaded) { return; }
this.$.reviewed.checked = reviewed;
- this._saveReviewedState(reviewed).catch(function(err) {
- alert('Couldn’t change file review status. Check the console ' +
- 'and contact the PolyGerrit team for assistance.');
+ this._saveReviewedState(reviewed).catch(err => {
+ this.fire('show-alert', {message: ERR_REVIEW_STATUS});
throw err;
- }.bind(this));
+ });
},
- _saveReviewedState: function(reviewed) {
+ _saveReviewedState(reviewed) {
return this.$.restAPI.saveFileReviewed(this._changeNum,
this._patchRange.patchNum, this._path, reviewed);
},
- _handleEscKey: function(e) {
+ _handleEscKey(e) {
if (this.shouldSuppressKeyboardShortcut(e) ||
this.modifierPressed(e)) { return; }
@@ -220,21 +247,21 @@
this.$.diff.displayLine = false;
},
- _handleShiftLeftKey: function(e) {
+ _handleShiftLeftKey(e) {
if (this.shouldSuppressKeyboardShortcut(e)) { return; }
e.preventDefault();
this.$.cursor.moveLeft();
},
- _handleShiftRightKey: function(e) {
+ _handleShiftRightKey(e) {
if (this.shouldSuppressKeyboardShortcut(e)) { return; }
e.preventDefault();
this.$.cursor.moveRight();
},
- _handleUpKey: function(e) {
+ _handleUpKey(e) {
if (this.shouldSuppressKeyboardShortcut(e)) { return; }
if (e.detail.keyboardEvent.shiftKey &&
e.detail.keyboardEvent.keyCode === 75) { // 'K'
@@ -248,7 +275,7 @@
this.$.cursor.moveUp();
},
- _handleDownKey: function(e) {
+ _handleDownKey(e) {
if (this.shouldSuppressKeyboardShortcut(e)) { return; }
if (e.detail.keyboardEvent.shiftKey &&
e.detail.keyboardEvent.keyCode === 74) { // 'J'
@@ -262,49 +289,51 @@
this.$.cursor.moveDown();
},
- _moveToPreviousFileWithComment: function() {
+ _moveToPreviousFileWithComment() {
if (this._commentSkips && this._commentSkips.previous) {
- page.show(this._getDiffURL(this._changeNum, this._patchRange,
- this._commentSkips.previous));
+ Gerrit.Nav.navigateToDiff(this._change, this._commentSkips.previous,
+ this._patchRange.patchNum, this._patchRange.basePatchNum);
}
},
- _moveToNextFileWithComment: function() {
+ _moveToNextFileWithComment() {
if (this._commentSkips && this._commentSkips.next) {
- page.show(this._getDiffURL(this._changeNum, this._patchRange,
- this._commentSkips.next));
+ Gerrit.Nav.navigateToDiff(this._change, this._commentSkips.next,
+ this._patchRange.patchNum, this._patchRange.basePatchNum);
}
},
- _handleCKey: function(e) {
+ _handleCKey(e) {
if (this.shouldSuppressKeyboardShortcut(e)) { return; }
if (this.$.diff.isRangeSelected()) { return; }
if (this.modifierPressed(e)) { return; }
e.preventDefault();
- var line = this.$.cursor.getTargetLineElement();
+ const line = this.$.cursor.getTargetLineElement();
if (line) {
this.$.diff.addDraftAtLine(line);
}
},
- _handleLeftBracketKey: function(e) {
+ _handleLeftBracketKey(e) {
+ // Check for meta key to avoid overriding native chrome shortcut.
if (this.shouldSuppressKeyboardShortcut(e) ||
- this.modifierPressed(e)) { return; }
+ this.getKeyboardEvent(e).metaKey) { return; }
e.preventDefault();
this._navToFile(this._path, this._fileList, -1);
},
- _handleRightBracketKey: function(e) {
+ _handleRightBracketKey(e) {
+ // Check for meta key to avoid overriding native chrome shortcut.
if (this.shouldSuppressKeyboardShortcut(e) ||
- this.modifierPressed(e)) { return; }
+ this.getKeyboardEvent(e).metaKey) { return; }
e.preventDefault();
this._navToFile(this._path, this._fileList, 1);
},
- _handleNKey: function(e) {
+ _handleNKey(e) {
if (this.shouldSuppressKeyboardShortcut(e)) { return; }
e.preventDefault();
@@ -316,7 +345,7 @@
}
},
- _handlePKey: function(e) {
+ _handlePKey(e) {
if (this.shouldSuppressKeyboardShortcut(e)) { return; }
e.preventDefault();
@@ -328,7 +357,7 @@
}
},
- _handleAKey: function(e) {
+ _handleAKey(e) {
if (this.shouldSuppressKeyboardShortcut(e)) { return; }
if (e.detail.keyboardEvent.shiftKey) { // Hide left diff.
@@ -340,18 +369,13 @@
if (this.modifierPressed(e)) { return; }
if (!this._loggedIn) { return; }
- if (this.$.restAPI.hasPendingDiffDrafts()) {
- this.dispatchEvent(new CustomEvent('show-alert',
- {detail: {message: COMMENT_SAVE}, bubbles: true}));
- return;
- }
this.set('changeViewState.showReplyDialog', true);
e.preventDefault();
this._navToChangeView();
},
- _handleUKey: function(e) {
+ _handleUKey(e) {
if (this.shouldSuppressKeyboardShortcut(e) ||
this.modifierPressed(e)) { return; }
@@ -359,49 +383,41 @@
this._navToChangeView();
},
- _handleCommaKey: function(e) {
+ _handleCommaKey(e) {
if (this.shouldSuppressKeyboardShortcut(e) ||
this.modifierPressed(e)) { return; }
e.preventDefault();
- this._openPrefs();
+ this.$.diffPreferences.open();
},
- _navToChangeView: function() {
+ _navToChangeView() {
if (!this._changeNum || !this._patchRange.patchNum) { return; }
-
- page.show(this._getChangePath(
- this._changeNum,
+ this._navigateToChange(
+ this._change,
this._patchRange,
- this._change && this._change.revisions));
- },
-
- _computeUpURL: function(changeNum, patchRange, change, changeRevisions) {
- return this._getChangePath(
- changeNum,
- patchRange,
- change && changeRevisions);
+ this._change && this._change.revisions);
},
- _navToFile: function(path, fileList, direction) {
- var url = this._computeNavLinkURL(path, fileList, direction);
- if (!url) { return; }
+ _navToFile(path, fileList, direction) {
+ const newPath = this._getNavLinkPath(path, fileList, direction);
+ if (!newPath) { return; }
- page.show(this._computeNavLinkURL(path, fileList, direction));
- },
+ if (newPath.up) {
+ this._navigateToChange(
+ this._change,
+ this._patchRange,
+ this._change && this._change.revisions);
+ return;
+ }
- _openPrefs: function() {
- this.$.prefsOverlay.open().then(function() {
- var diffPreferences = this.$.diffPreferences;
- var focusStops = diffPreferences.getFocusStops();
- this.$.prefsOverlay.setFocusStops(focusStops);
- this.$.diffPreferences.resetFocus();
- }.bind(this));
+ Gerrit.Nav.navigateToDiff(this._change, newPath.path,
+ this._patchRange.patchNum, this._patchRange.basePatchNum);
},
/**
* @param {?string} path The path of the current file being shown.
- * @param {Array.<string>} fileList The list of files in this change and
+ * @param {!Array<string>} fileList The list of files in this change and
* patch range.
* @param {number} direction Either 1 (next file) or -1 (prev file).
* @param {(number|boolean)} opt_noUp Whether to return to the change view
@@ -410,13 +426,46 @@
* @return {?string} The next URL when proceeding in the specified
* direction.
*/
- _computeNavLinkURL: function(path, fileList, direction, opt_noUp) {
+ _computeNavLinkURL(change, path, fileList, direction, opt_noUp) {
+ const newPath = this._getNavLinkPath(path, fileList, direction, opt_noUp);
+ if (!newPath) { return null; }
+
+ if (newPath.up) {
+ return this._getChangePath(
+ this._change,
+ this._patchRange,
+ this._change && this._change.revisions);
+ }
+ return this._getDiffUrl(this._change, this._patchRange, newPath.path);
+ },
+
+ /**
+ * Gives an object representing the target of navigating either left or
+ * right through the change. The resulting object will have one of the
+ * following forms:
+ * * {path: "<target file path>"} - When another file path should be the
+ * result of the navigation.
+ * * {up: true} - When the result of navigating should go back to the
+ * change view.
+ * * null - When no navigation is possible for the given direction.
+ *
+ * @param {?string} path The path of the current file being shown.
+ * @param {!Array<string>} fileList The list of files in this change and
+ * patch range.
+ * @param {number} direction Either 1 (next file) or -1 (prev file).
+ * @param {?number|boolean=} opt_noUp Whether to return to the change view
+ * when advancing the file goes outside the bounds of fileList.
+ * @return {?Object}
+ */
+ _getNavLinkPath(path, fileList, direction, opt_noUp) {
if (!path || fileList.length === 0) { return null; }
- var idx = fileList.indexOf(path);
+ let idx = fileList.indexOf(path);
if (idx === -1) {
- var file = direction > 0 ? fileList[0] : fileList[fileList.length - 1];
- return this._getDiffURL(this._changeNum, this._patchRange, file);
+ const file = direction > 0 ?
+ fileList[0] :
+ fileList[fileList.length - 1];
+ return {path: file};
}
idx += direction;
@@ -424,28 +473,31 @@
// outside the bounds of [0, fileList.length).
if (idx < 0 || idx > fileList.length - 1) {
if (opt_noUp) { return null; }
- return this._getChangePath(
- this._changeNum,
- this._patchRange,
- this._change && this._change.revisions);
+ return {up: true};
}
- return this._getDiffURL(this._changeNum, this._patchRange, fileList[idx]);
+
+ return {path: fileList[idx]};
},
- _paramsChanged: function(value) {
- if (value.view != this.tagName.toLowerCase()) { return; }
+ _paramsChanged(value) {
+ if (value.view !== Gerrit.Nav.View.DIFF) { return; }
- this._loadHash(location.hash);
+ this._initCursor(this.params);
this._changeNum = value.changeNum;
this._patchRange = {
patchNum: value.patchNum,
- basePatchNum: value.basePatchNum || 'PARENT',
+ basePatchNum: value.basePatchNum || PARENT,
};
this._path = value.path;
- this.fire('title-change',
- {title: this._computeFileDisplayName(this._path)});
+ // NOTE: This may be called before attachment (e.g. while parentElement is
+ // null). Fire title-change in an async so that, if attachment to the DOM
+ // has been queued, the event can bubble up to the handler in gr-app.
+ this.async(() => {
+ this.fire('title-change',
+ {title: this.computeTruncatedPath(this._path)});
+ });
// When navigating away from the page, there is a possibility that the
// patch number is no longer a part of the URL (say when navigating to
@@ -454,128 +506,146 @@
return;
}
- var promises = [];
+ const promises = [];
this._localPrefs = this.$.storage.getPreferences();
- promises.push(this._getDiffPreferences().then(function(prefs) {
+ promises.push(this._getDiffPreferences().then(prefs => {
this._prefs = prefs;
- }.bind(this)));
+ }));
- promises.push(this._getPreferences().then(function(prefs) {
+ promises.push(this._getPreferences().then(prefs => {
this._userPrefs = prefs;
- }.bind(this)));
+ }));
promises.push(this._getChangeDetail(this._changeNum));
- Promise.all(promises).then(function() {
+ promises.push(this._loadComments());
+
+ promises.push(this._getChangeEdit(this._changeNum));
+
+ this._loading = true;
+ Promise.all(promises).then(r => {
+ const edit = r[4];
+ if (edit) {
+ this.set('_change.revisions.' + edit.commit.commit, {
+ _number: this.EDIT_NAME,
+ basePatchNum: edit.base_patch_set_number,
+ commit: edit.commit,
+ });
+ }
this._loading = false;
+ this.$.diff.comments = this._commentsForDiff;
this.$.diff.reload();
- }.bind(this));
+ });
+ },
- this._loadCommentMap().then(function(commentMap) {
- this._commentMap = commentMap;
- }.bind(this));
+ _changeViewStateChanged(changeViewState) {
+ if (changeViewState.diffMode === null) {
+ // If screen size is small, always default to unified view.
+ this.$.restAPI.getPreferences().then(prefs => {
+ this.set('changeViewState.diffMode', prefs.default_diff_view);
+ });
+ }
+ },
+
+ _setReviewedObserver(_loggedIn) {
+ if (_loggedIn) {
+ this._setReviewed(true);
+ }
},
/**
- * If the URL hash is a diff address then configure the diff cursor.
+ * If the params specify a diff address then configure the diff cursor.
*/
- _loadHash: function(hash) {
- hash = hash.replace(/^#/, '');
- if (!HASH_PATTERN.test(hash)) { return; }
- if (hash[0] === 'a' || hash[0] === 'b') {
+ _initCursor(params) {
+ if (params.lineNum === undefined) { return; }
+ if (params.leftSide) {
this.$.cursor.side = DiffSides.LEFT;
- hash = hash.substring(1);
} else {
this.$.cursor.side = DiffSides.RIGHT;
}
- this.$.cursor.initialLineNumber = parseInt(hash, 10);
+ this.$.cursor.initialLineNumber = params.lineNum;
},
- _pathChanged: function(path) {
+ _pathChanged(path) {
+ if (path) {
+ this.fire('title-change',
+ {title: this.computeTruncatedPath(path)});
+ }
+
if (this._fileList.length == 0) { return; }
this.set('changeViewState.selectedFileIndex',
this._fileList.indexOf(path));
-
- if (this._loggedIn) {
- this._setReviewed(true);
- }
},
- _getDiffURL: function(changeNum, patchRange, path) {
- return this.getBaseUrl() + '/c/' + changeNum + '/' +
- this._patchRangeStr(patchRange) + '/' + this.encodeURL(path, true);
+ _getDiffUrl(change, patchRange, path) {
+ return Gerrit.Nav.getUrlForDiff(change, path, patchRange.patchNum,
+ patchRange.basePatchNum);
},
- _computeDiffURL: function(changeNum, patchRangeRecord, path) {
- return this._getDiffURL(changeNum, patchRangeRecord.base, path);
+ _computeDiffURL(change, patchRangeRecord, path) {
+ return this._getDiffUrl(change, patchRangeRecord.base, path);
},
- _patchRangeStr: function(patchRange) {
- var patchStr = patchRange.patchNum;
+ _patchRangeStr(patchRange) {
+ let patchStr = patchRange.patchNum;
if (patchRange.basePatchNum != null &&
- patchRange.basePatchNum != 'PARENT') {
+ patchRange.basePatchNum != PARENT) {
patchStr = patchRange.basePatchNum + '..' + patchRange.patchNum;
}
return patchStr;
},
- _computeAvailablePatches: function(revisions) {
- var patchNums = [];
- for (var rev in revisions) {
- patchNums.push(revisions[rev]._number);
- }
- return patchNums.sort(function(a, b) { return a - b; });
- },
-
- _getChangePath: function(changeNum, patchRange, revisions) {
- var base = this.getBaseUrl() + '/c/' + changeNum + '/';
-
- // The change may not have loaded yet, making revisions unavailable.
- if (!revisions) {
- return base + this._patchRangeStr(patchRange);
- }
-
- var latestPatchNum = -1;
- for (var rev in revisions) {
- latestPatchNum = Math.max(latestPatchNum, revisions[rev]._number);
+ /**
+ * When the latest patch of the change is selected (and there is no base
+ * patch) then the patch range need not appear in the URL. Return a patch
+ * range object with undefined values when a range is not needed.
+ *
+ * @param {!Object} patchRange
+ * @param {!Object} revisions
+ * @return {!Object}
+ */
+ _getChangeUrlRange(patchRange, revisions) {
+ let patchNum = undefined;
+ let basePatchNum = undefined;
+ let latestPatchNum = -1;
+ for (const rev of Object.values(revisions || {})) {
+ latestPatchNum = Math.max(latestPatchNum, rev._number);
}
- if (patchRange.basePatchNum !== 'PARENT' ||
+ if (patchRange.basePatchNum !== PARENT ||
parseInt(patchRange.patchNum, 10) !== latestPatchNum) {
- return base + this._patchRangeStr(patchRange);
+ patchNum = patchRange.patchNum;
+ basePatchNum = patchRange.basePatchNum;
}
-
- return base;
+ return {patchNum, basePatchNum};
},
- _computeChangePath: function(changeNum, patchRangeRecord, revisions) {
- return this._getChangePath(changeNum, patchRangeRecord.base, revisions);
+ _getChangePath(change, patchRange, revisions) {
+ const range = this._getChangeUrlRange(patchRange, revisions);
+ return Gerrit.Nav.getUrlForChange(change, range.patchNum,
+ range.basePatchNum);
},
- _computeFileDisplayName: function(path) {
- if (path === COMMIT_MESSAGE_PATH) {
- return 'Commit message';
- } else if (path === MERGE_LIST_PATH) {
- return 'Merge list';
- }
- return path;
+ _navigateToChange(change, patchRange, revisions) {
+ const range = this._getChangeUrlRange(patchRange, revisions);
+ Gerrit.Nav.navigateToChange(change, range.patchNum, range.basePatchNum);
},
- _computeTruncatedFileDisplayName: function(path) {
- return util.truncatePath(this._computeFileDisplayName(path));
+ _computeChangePath(change, patchRangeRecord, revisions) {
+ return this._getChangePath(change, patchRangeRecord.base, revisions);
},
- _computeFileSelected: function(path, currentPath) {
+ _computeFileSelected(path, currentPath) {
return path == currentPath;
},
- _computePrefsButtonHidden: function(prefs, loggedIn) {
+ _computePrefsButtonHidden(prefs, loggedIn) {
return !loggedIn || !prefs;
},
- _computeKeyNav: function(path, selectedPath, fileList) {
- var selectedIndex = fileList.indexOf(selectedPath);
+ _computeKeyNav(path, selectedPath, fileList) {
+ const selectedIndex = fileList.indexOf(selectedPath);
if (fileList.indexOf(path) == selectedIndex - 1) {
return '[';
}
@@ -585,46 +655,50 @@
return '';
},
- _handleFileTap: function(e) {
- this.$.dropdown.close();
+ _handleFileTap(e) {
+ // async is needed so that that the click event is fired before the
+ // dropdown closes (This was a bug for touch devices).
+ this.async(() => {
+ this.$.dropdown.close();
+ }, 1);
},
- _handleMobileSelectChange: function(e) {
- var path = Polymer.dom(e).rootTarget.value;
- page.show(this._getDiffURL(this._changeNum, this._patchRange, path));
+ _handleMobileSelectChange(e) {
+ const path = Polymer.dom(e).rootTarget.value;
+ Gerrit.Nav.navigateToDiff(this._change, path, this._patchRange.patchNum,
+ this._patchRange.basePatchNum);
},
- _showDropdownTapHandler: function(e) {
+ _showDropdownTapHandler(e) {
this.$.dropdown.open();
},
- _handlePrefsTap: function(e) {
+ _handlePatchChange(e) {
+ const {basePatchNum, patchNum} = e.detail;
+ if (this.patchNumEquals(basePatchNum, this._patchRange.basePatchNum) &&
+ this.patchNumEquals(patchNum, this._patchRange.patchNum)) { return; }
+ Gerrit.Nav.navigateToDiff(
+ this._change, this._path, patchNum, basePatchNum);
+ },
+
+ _handlePrefsTap(e) {
e.preventDefault();
- this._openPrefs();
+ this.$.diffPreferences.open();
},
- _handlePrefsSave: function(e) {
+ _handlePrefsSave(e) {
e.stopPropagation();
- var el = Polymer.dom(e).rootTarget;
+ const el = Polymer.dom(e).rootTarget;
el.disabled = true;
this.$.storage.savePreferences(this._localPrefs);
- this._saveDiffPreferences().then(function(response) {
+ this._saveDiffPreferences().then(response => {
el.disabled = false;
if (!response.ok) { return response; }
this.$.prefsOverlay.close();
- }.bind(this)).catch(function(err) {
+ }).catch(err => {
el.disabled = false;
- }.bind(this));
- },
-
- _saveDiffPreferences: function() {
- return this.$.restAPI.saveDiffPreferences(this._prefs);
- },
-
- _handlePrefsCancel: function(e) {
- e.stopPropagation();
- this.$.prefsOverlay.close();
+ });
},
/**
@@ -639,9 +713,9 @@
*
* Use side-by-side if the user is not logged in.
*
- * @return {String}
+ * @return {string}
*/
- _getDiffViewMode: function() {
+ _getDiffViewMode() {
if (this.changeViewState.diffMode) {
return this.changeViewState.diffMode;
} else if (this._userPrefs) {
@@ -652,66 +726,48 @@
}
},
- _computeModeSelectHidden: function() {
+ _computeModeSelectHidden() {
return this._isImageDiff;
},
- _onLineSelected: function(e, detail) {
+ _onLineSelected(e, detail) {
this.$.cursor.moveToLineNumber(detail.number, detail.side);
- history.replaceState(null, null, '#' + this.$.cursor.getAddress());
- },
-
- _computeDownloadLink: function(changeNum, patchRange, path) {
- var url = this.changeBaseURL(changeNum, patchRange.patchNum);
+ if (!this._change) { return; }
+ const cursorAddress = this.$.cursor.getAddress();
+ const number = cursorAddress ? cursorAddress.number : undefined;
+ const leftSide = cursorAddress ? cursorAddress.leftSide : undefined;
+ const url = Gerrit.Nav.getUrlForDiffById(this._changeNum,
+ this._change.project, this._path, this._patchRange.patchNum,
+ this._patchRange.basePatchNum, number, leftSide);
+ history.replaceState(null, '', url);
+ },
+
+ _computeDownloadLink(changeNum, patchRange, path) {
+ let url = this.changeBaseURL(changeNum, patchRange.patchNum);
url += '/patch?zip&path=' + encodeURIComponent(path);
return url;
},
- /**
- * Request all comments (and drafts and robot comments) for the current
- * change and construct the map of file paths that have comments for the
- * current patch range.
- * @return {Promise} A promise that yields a comment map object.
- */
- _loadCommentMap: function() {
- function filterByRange(comment) {
- var patchNum = comment.patch_set + '';
- return patchNum === this._patchRange.patchNum ||
- patchNum === this._patchRange.basePatchNum;
- };
+ _loadComments() {
+ return this.$.commentAPI.loadAll(this._changeNum).then(() => {
+ this._commentMap = this.$.commentAPI.getPaths(this._patchRange);
+
+ this._commentsForDiff = this.$.commentAPI.getCommentsForPath(this._path,
+ this._patchRange, this._projectConfig);
+ });
+ },
+
+ _getDiffDrafts() {
+ return this.$.restAPI.getDiffDrafts(this._changeNum);
+ },
- return Promise.all([
- this.$.restAPI.getDiffComments(this._changeNum),
- this._getDiffDrafts(),
- this.$.restAPI.getDiffRobotComments(this._changeNum),
- ]).then(function(results) {
- var commentMap = {};
- results.forEach(function(response) {
- for (var path in response) {
- if (response.hasOwnProperty(path) &&
- response[path].filter(filterByRange.bind(this)).length) {
- commentMap[path] = true;
- }
- }
- }.bind(this));
- return commentMap;
- }.bind(this));
- },
-
- _getDiffDrafts: function() {
- return this._getLoggedIn().then(function(loggedIn) {
- if (!loggedIn) { return Promise.resolve({}); }
- return this.$.restAPI.getDiffDrafts(this._changeNum);
- }.bind(this));
- },
-
- _computeCommentSkips: function(commentMap, fileList, path) {
- var skips = {previous: null, next: null};
+ _computeCommentSkips(commentMap, fileList, path) {
+ const skips = {previous: null, next: null};
if (!fileList.length) { return skips; }
- var pathIndex = fileList.indexOf(path);
+ const pathIndex = fileList.indexOf(path);
// Scan backward for the previous file.
- for (var i = pathIndex - 1; i >= 0; i--) {
+ for (let i = pathIndex - 1; i >= 0; i--) {
if (commentMap[fileList[i]]) {
skips.previous = fileList[i];
break;
@@ -719,7 +775,7 @@
}
// Scan forward for the next file.
- for (i = pathIndex + 1; i < fileList.length; i++) {
+ for (let i = pathIndex + 1; i < fileList.length; i++) {
if (commentMap[fileList[i]]) {
skips.next = fileList[i];
break;
@@ -728,5 +784,57 @@
return skips;
},
+
+ _computeDiffClass(panelFloatingDisabled) {
+ if (panelFloatingDisabled) {
+ return 'noOverflow';
+ }
+ },
+
+ /**
+ * @param {!Object} patchRangeRecord
+ */
+ _computeEditLoaded(patchRangeRecord) {
+ const patchRange = patchRangeRecord.base || {};
+ return this.patchNumEquals(patchRange.patchNum, this.EDIT_NAME);
+ },
+
+ /**
+ * @param {boolean} editLoaded
+ */
+ _computeContainerClass(editLoaded) {
+ return editLoaded ? 'editLoaded' : '';
+ },
+
+ _computeBlameToggleLabel(loaded, loading) {
+ if (loaded) { return 'Hide blame'; }
+ return 'Show blame';
+ },
+
+ /**
+ * Load and display blame information if it has not already been loaded.
+ * Otherwise hide it.
+ */
+ _toggleBlame() {
+ if (this._isBlameLoaded) {
+ this.$.diff.clearBlame();
+ return;
+ }
+
+ this._isBlameLoading = true;
+ this.fire('show-alert', {message: MSG_LOADING_BLAME});
+ this.$.diff.loadBlame()
+ .then(() => {
+ this._isBlameLoading = false;
+ this.fire('show-alert', {message: MSG_LOADED_BLAME});
+ })
+ .catch(() => {
+ this._isBlameLoading = false;
+ });
+ },
+
+ _computeBlameLoaderClass(isImageDiff, supported) {
+ return !isImageDiff && supported ? 'show' : '';
+ },
});
})();