blob: 90a391388da0ee58c8347dbd257fb4c95dd1dead [file] [log] [blame]
Andrew Bonventre78792e82016-03-04 17:48:22 -05001// Copyright (C) 2016 The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14(function() {
15 'use strict';
16
Kasper Nilssonde211a52017-07-11 14:50:51 -070017 const ERR_REVIEW_STATUS = 'Couldn’t change file review status.';
Wyatt Allened628d72017-09-14 09:45:50 -070018 const MSG_LOADING_BLAME = 'Loading blame...';
19 const MSG_LOADED_BLAME = 'Blame loaded';
Kasper Nilssonde211a52017-07-11 14:50:51 -070020
Wyatt Allendc8782d2017-07-26 09:32:03 -070021 const PARENT = 'PARENT';
22
Kasper Nilssonef511942017-05-16 14:38:48 -070023 const DiffSides = {
Wyatt Allenbdd4e342016-06-20 14:38:33 -070024 LEFT: 'left',
25 RIGHT: 'right',
26 };
27
Wyatt Allen61e414c2018-02-06 17:02:17 -080028 const DiffViewMode = {
29 SIDE_BY_SIDE: 'SIDE_BY_SIDE',
30 UNIFIED: 'UNIFIED_DIFF',
31 };
32
Andrew Bonventre78792e82016-03-04 17:48:22 -050033 Polymer({
34 is: 'gr-diff-view',
35
36 /**
37 * Fired when the title of the page should change.
38 *
39 * @event title-change
40 */
41
Kasper Nilsson6cff0e62017-02-06 14:50:53 -080042 /**
43 * Fired when user tries to navigate away while comments are pending save.
44 *
45 * @event show-alert
46 */
47
Andrew Bonventre78792e82016-03-04 17:48:22 -050048 properties: {
Andrew Bonventre78792e82016-03-04 17:48:22 -050049 /**
50 * URL params passed from the router.
51 */
52 params: {
53 type: Object,
54 observer: '_paramsChanged',
55 },
56 keyEventTarget: {
57 type: Object,
Kasper Nilssonef511942017-05-16 14:38:48 -070058 value() { return document.body; },
Andrew Bonventre78792e82016-03-04 17:48:22 -050059 },
Becky Siegel8d92d532017-08-11 16:32:47 -070060 /**
61 * @type {{ diffMode: (string|undefined) }}
62 */
Andrew Bonventre78792e82016-03-04 17:48:22 -050063 changeViewState: {
64 type: Object,
65 notify: true,
Kasper Nilssonef511942017-05-16 14:38:48 -070066 value() { return {}; },
Kasper Nilsson143a4272017-07-12 12:47:14 -070067 observer: '_changeViewStateChanged',
Andrew Bonventre78792e82016-03-04 17:48:22 -050068 },
Becky Siegelaf950fd2017-10-12 11:35:18 -070069 /** @type {?} */
Andrew Bonventre78792e82016-03-04 17:48:22 -050070 _patchRange: Object,
Viktar Donicha28dee062017-11-10 16:03:13 -080071 /** @type {?} */
72 _commitRange: Object,
Becky Siegel8d92d532017-08-11 16:32:47 -070073 /**
74 * @type {{
75 * subject: string,
76 * project: string,
77 * revisions: string,
78 * }}
79 */
Andrew Bonventre78792e82016-03-04 17:48:22 -050080 _change: Object,
Becky Siegel318f2ad2017-11-06 15:36:10 -080081 /** @type {?} */
Becky Siegelc7f07dc2017-11-02 16:07:13 -070082 _changeComments: Object,
Andrew Bonventre78792e82016-03-04 17:48:22 -050083 _changeNum: String,
84 _diff: Object,
Becky Siegelfde2da62017-11-07 15:49:55 -080085 // An array specifically formatted to be used in a gr-dropdown-list
86 // element for selected a file to view.
87 _formattedFiles: {
88 type: Array,
Becky Siegel5946f952017-11-09 11:53:33 -080089 computed: '_formatFilesForDropdown(_fileList, _patchRange.patchNum, ' +
90 '_changeComments)',
Becky Siegelfde2da62017-11-07 15:49:55 -080091 },
92 // An sorted array of files, as returned by the rest API.
Andrew Bonventre78792e82016-03-04 17:48:22 -050093 _fileList: {
94 type: Array,
Kasper Nilssonef511942017-05-16 14:38:48 -070095 value() { return []; },
Andrew Bonventre78792e82016-03-04 17:48:22 -050096 },
97 _path: {
98 type: String,
99 observer: '_pathChanged',
100 },
Viktar Donichc5069b12018-01-30 16:17:13 -0800101 _fileNum: {
102 type: Number,
103 computed: '_computeFileNum(_path, _formattedFiles)',
104 },
Andrew Bonventre78792e82016-03-04 17:48:22 -0500105 _loggedIn: {
106 type: Boolean,
107 value: false,
108 },
Andrew Bonventrec80291c2016-04-23 23:18:43 -0400109 _loading: {
110 type: Boolean,
111 value: true,
112 },
113 _prefs: Object,
Viktar Donich5008b442016-06-08 12:37:31 -0700114 _localPrefs: Object,
Urs Wolferc047fcd2016-05-29 18:12:56 +0200115 _projectConfig: Object,
Wyatt Allenf93f1c242016-05-05 16:53:38 -0700116 _userPrefs: Object,
117 _diffMode: {
118 type: String,
Viktar Donichb34d1f82016-08-03 13:16:36 -0700119 computed: '_getDiffViewMode(changeViewState.diffMode, _userPrefs)',
Wyatt Allenf93f1c242016-05-05 16:53:38 -0700120 },
Wyatt Allen88678da2016-05-23 17:18:43 -0700121 _isImageDiff: Boolean,
Viktar Donichb34d1f82016-08-03 13:16:36 -0700122 _filesWeblinks: Object,
Wyatt Allen1bc4f2f2017-01-18 17:10:51 -0800123
124 /**
Kasper Nilsson6cff0e62017-02-06 14:50:53 -0800125 * Map of paths in the current change and patch range that have comments
Wyatt Allen1bc4f2f2017-01-18 17:10:51 -0800126 * or drafts or robot comments.
127 */
128 _commentMap: Object,
129
Wyatt Allendc8782d2017-07-26 09:32:03 -0700130 _commentsForDiff: Object,
131
Wyatt Allen1bc4f2f2017-01-18 17:10:51 -0800132 /**
133 * Object to contain the path of the next and previous file in the current
134 * change and patch range that has comments.
135 */
136 _commentSkips: {
137 type: Object,
138 computed: '_computeCommentSkips(_commentMap, _fileList, _path)',
139 },
Viktar Donich168bbc92017-06-19 14:50:09 -0700140 _panelFloatingDisabled: {
141 type: Boolean,
142 value: () => { return window.PANEL_FLOATING_DISABLED; },
143 },
Kasper Nilsson808838e2018-01-23 17:15:38 -0800144 _editMode: {
Kasper Nilsson5f1f0c62017-08-08 14:04:54 -0700145 type: Boolean,
Kasper Nilsson808838e2018-01-23 17:15:38 -0800146 computed: '_computeEditMode(_patchRange.*)',
Kasper Nilsson5f1f0c62017-08-08 14:04:54 -0700147 },
Wyatt Allened628d72017-09-14 09:45:50 -0700148 _isBlameSupported: {
149 type: Boolean,
150 value: false,
151 },
152 _isBlameLoaded: Boolean,
153 _isBlameLoading: {
154 type: Boolean,
155 value: false,
156 },
Becky Siegelfd7c71f2017-09-26 09:59:33 -0700157 _allPatchSets: {
158 type: Array,
159 computed: 'computeAllPatchSets(_change, _change.revisions.*)',
160 },
Wyatt Allena744e232017-11-08 15:33:48 -0800161 _revisionInfo: {
162 type: Object,
163 computed: '_getRevisionInfo(_change)',
164 },
Andrew Bonventre78792e82016-03-04 17:48:22 -0500165 },
166
167 behaviors: [
168 Gerrit.KeyboardShortcutBehavior,
Kasper Nilsson9060cfd2017-07-21 14:07:48 -0700169 Gerrit.PatchSetBehavior,
Kasper Nilssonce67e2a2017-09-12 14:15:44 -0700170 Gerrit.PathListBehavior,
Kasper Nilssonc59e880582016-10-21 11:01:08 -0700171 Gerrit.RESTClientBehavior,
Andrew Bonventre30344cc2016-04-05 16:06:57 -0400172 ],
173
174 observers: [
Andrew Bonventre30344cc2016-04-05 16:06:57 -0400175 '_getProjectConfig(_change.project)',
Andrew Bonventre91c62932016-05-11 14:31:49 -0400176 '_getFiles(_changeNum, _patchRange.*)',
Kasper Nilssonf428a232018-02-07 11:37:22 -0800177 '_setReviewedObserver(_loggedIn, params.*, _prefs)',
Andrew Bonventre78792e82016-03-04 17:48:22 -0500178 ],
179
Andrew Bonventre4d22c7e2016-11-15 17:01:15 -0800180 keyBindings: {
181 'esc': '_handleEscKey',
182 'shift+left': '_handleShiftLeftKey',
183 'shift+right': '_handleShiftRightKey',
184 'up k': '_handleUpKey',
185 'down j': '_handleDownKey',
186 'c': '_handleCKey',
187 '[': '_handleLeftBracketKey',
188 ']': '_handleRightBracketKey',
189 'n shift+n': '_handleNKey',
190 'p shift+p': '_handlePKey',
191 'a shift+a': '_handleAKey',
192 'u': '_handleUKey',
193 ',': '_handleCommaKey',
Wyatt Allen61e414c2018-02-06 17:02:17 -0800194 'm': '_handleMKey',
Andrew Bonventre4d22c7e2016-11-15 17:01:15 -0800195 },
196
Kasper Nilssonef511942017-05-16 14:38:48 -0700197 attached() {
198 this._getLoggedIn().then(loggedIn => {
Andrew Bonventrecfacb802016-03-29 14:06:39 -0400199 this._loggedIn = loggedIn;
Kasper Nilssonef511942017-05-16 14:38:48 -0700200 });
Wyatt Allen0b6fe192016-05-17 09:46:00 -0700201
Wyatt Allened628d72017-09-14 09:45:50 -0700202 this.$.restAPI.getConfig().then(config => {
203 this._isBlameSupported = config.change.allow_blame;
204 });
205
Wyatt Allen0b6fe192016-05-17 09:46:00 -0700206 this.$.cursor.push('diffs', this.$.diff);
Andrew Bonventre78792e82016-03-04 17:48:22 -0500207 },
208
Kasper Nilssonef511942017-05-16 14:38:48 -0700209 _getLoggedIn() {
Andrew Bonventrecfacb802016-03-29 14:06:39 -0400210 return this.$.restAPI.getLoggedIn();
211 },
212
Kasper Nilssonef511942017-05-16 14:38:48 -0700213 _getProjectConfig(project) {
Andrew Bonventre30344cc2016-04-05 16:06:57 -0400214 return this.$.restAPI.getProjectConfig(project).then(
Kasper Nilssonef511942017-05-16 14:38:48 -0700215 config => {
Andrew Bonventre30344cc2016-04-05 16:06:57 -0400216 this._projectConfig = config;
Kasper Nilssonef511942017-05-16 14:38:48 -0700217 });
Andrew Bonventre30344cc2016-04-05 16:06:57 -0400218 },
219
Kasper Nilssonef511942017-05-16 14:38:48 -0700220 _getChangeDetail(changeNum) {
Kasper Nilssonf89608d2017-07-24 15:06:07 -0700221 return this.$.restAPI.getDiffChangeDetail(changeNum).then(change => {
222 this._change = change;
Viktar Donicha28dee062017-11-10 16:03:13 -0800223 return change;
Kasper Nilssonf89608d2017-07-24 15:06:07 -0700224 });
225 },
226
David Ostrovskye6a6f442017-04-25 23:48:05 +0200227 _getChangeEdit(changeNum) {
228 return this.$.restAPI.getChangeEdit(this._changeNum);
229 },
230
Kasper Nilssonef511942017-05-16 14:38:48 -0700231 _getFiles(changeNum, patchRangeRecord) {
232 const patchRange = patchRangeRecord.base;
Andrew Bonventre2c6e1622016-04-14 17:52:07 -0400233 return this.$.restAPI.getChangeFilePathsAsSpeciallySortedArray(
Kasper Nilssonef511942017-05-16 14:38:48 -0700234 changeNum, patchRange).then(files => {
Andrew Bonventre2c6e1622016-04-14 17:52:07 -0400235 this._fileList = files;
Kasper Nilssonef511942017-05-16 14:38:48 -0700236 });
Andrew Bonventre30344cc2016-04-05 16:06:57 -0400237 },
238
Kasper Nilssonef511942017-05-16 14:38:48 -0700239 _getDiffPreferences() {
Andrew Bonventre61bcdbc2016-05-03 18:11:00 -0400240 return this.$.restAPI.getDiffPreferences();
Andrew Bonventrec80291c2016-04-23 23:18:43 -0400241 },
242
Kasper Nilssonef511942017-05-16 14:38:48 -0700243 _getPreferences() {
Wyatt Allenf93f1c242016-05-05 16:53:38 -0700244 return this.$.restAPI.getPreferences();
245 },
246
Kasper Nilssonef511942017-05-16 14:38:48 -0700247 _getWindowWidth() {
Becky Siegel74f531c2016-10-07 17:22:16 -0700248 return window.innerWidth;
249 },
250
Kasper Nilssonef511942017-05-16 14:38:48 -0700251 _handleReviewedChange(e) {
Andrew Bonventre78792e82016-03-04 17:48:22 -0500252 this._setReviewed(Polymer.dom(e).rootTarget.checked);
253 },
254
Kasper Nilssonef511942017-05-16 14:38:48 -0700255 _setReviewed(reviewed) {
Kasper Nilsson808838e2018-01-23 17:15:38 -0800256 if (this._editMode) { return; }
Andrew Bonventre78792e82016-03-04 17:48:22 -0500257 this.$.reviewed.checked = reviewed;
Kasper Nilssonef511942017-05-16 14:38:48 -0700258 this._saveReviewedState(reviewed).catch(err => {
Kasper Nilssonde211a52017-07-11 14:50:51 -0700259 this.fire('show-alert', {message: ERR_REVIEW_STATUS});
Andrew Bonventre78792e82016-03-04 17:48:22 -0500260 throw err;
Kasper Nilssonef511942017-05-16 14:38:48 -0700261 });
Andrew Bonventre78792e82016-03-04 17:48:22 -0500262 },
263
Kasper Nilssonef511942017-05-16 14:38:48 -0700264 _saveReviewedState(reviewed) {
Andrew Bonventre30344cc2016-04-05 16:06:57 -0400265 return this.$.restAPI.saveFileReviewed(this._changeNum,
266 this._patchRange.patchNum, this._path, reviewed);
267 },
268
Kasper Nilssonef511942017-05-16 14:38:48 -0700269 _handleEscKey(e) {
Kasper Nilssonfa4b2fe2016-12-07 18:02:34 -0800270 if (this.shouldSuppressKeyboardShortcut(e) ||
271 this.modifierPressed(e)) { return; }
Andrew Bonventre78792e82016-03-04 17:48:22 -0500272
Andrew Bonventre4d22c7e2016-11-15 17:01:15 -0800273 e.preventDefault();
274 this.$.diff.displayLine = false;
275 },
Viktar Donichc282d7b2016-08-10 11:53:12 -0700276
Kasper Nilssonef511942017-05-16 14:38:48 -0700277 _handleShiftLeftKey(e) {
Andrew Bonventre4d22c7e2016-11-15 17:01:15 -0800278 if (this.shouldSuppressKeyboardShortcut(e)) { return; }
Andrew Bonventre78792e82016-03-04 17:48:22 -0500279
Andrew Bonventre4d22c7e2016-11-15 17:01:15 -0800280 e.preventDefault();
281 this.$.cursor.moveLeft();
282 },
283
Kasper Nilssonef511942017-05-16 14:38:48 -0700284 _handleShiftRightKey(e) {
Andrew Bonventre4d22c7e2016-11-15 17:01:15 -0800285 if (this.shouldSuppressKeyboardShortcut(e)) { return; }
286
287 e.preventDefault();
288 this.$.cursor.moveRight();
289 },
290
Kasper Nilssonef511942017-05-16 14:38:48 -0700291 _handleUpKey(e) {
Wyatt Allen1bc4f2f2017-01-18 17:10:51 -0800292 if (this.shouldSuppressKeyboardShortcut(e)) { return; }
293 if (e.detail.keyboardEvent.shiftKey &&
294 e.detail.keyboardEvent.keyCode === 75) { // 'K'
295 this._moveToPreviousFileWithComment();
296 return;
297 }
298 if (this.modifierPressed(e)) { return; }
Andrew Bonventre4d22c7e2016-11-15 17:01:15 -0800299
300 e.preventDefault();
301 this.$.diff.displayLine = true;
302 this.$.cursor.moveUp();
303 },
304
Kasper Nilssonef511942017-05-16 14:38:48 -0700305 _handleDownKey(e) {
Wyatt Allen1bc4f2f2017-01-18 17:10:51 -0800306 if (this.shouldSuppressKeyboardShortcut(e)) { return; }
307 if (e.detail.keyboardEvent.shiftKey &&
308 e.detail.keyboardEvent.keyCode === 74) { // 'J'
309 this._moveToNextFileWithComment();
310 return;
311 }
312 if (this.modifierPressed(e)) { return; }
Andrew Bonventre4d22c7e2016-11-15 17:01:15 -0800313
314 e.preventDefault();
315 this.$.diff.displayLine = true;
316 this.$.cursor.moveDown();
317 },
318
Kasper Nilssonef511942017-05-16 14:38:48 -0700319 _moveToPreviousFileWithComment() {
Wyatt Allen1b3eb9c2018-01-10 15:18:32 -0800320 if (!this._commentSkips) { return; }
321
322 // If there is no previous diff with comments, then return to the change
323 // view.
324 if (!this._commentSkips.previous) {
325 this._navToChangeView();
326 return;
Wyatt Allen1bc4f2f2017-01-18 17:10:51 -0800327 }
Wyatt Allen1b3eb9c2018-01-10 15:18:32 -0800328
329 Gerrit.Nav.navigateToDiff(this._change, this._commentSkips.previous,
330 this._patchRange.patchNum, this._patchRange.basePatchNum);
Wyatt Allen1bc4f2f2017-01-18 17:10:51 -0800331 },
332
Kasper Nilssonef511942017-05-16 14:38:48 -0700333 _moveToNextFileWithComment() {
Wyatt Allen1b3eb9c2018-01-10 15:18:32 -0800334 if (!this._commentSkips) { return; }
335
336 // If there is no next diff with comments, then return to the change view.
337 if (!this._commentSkips.next) {
338 this._navToChangeView();
339 return;
Wyatt Allen1bc4f2f2017-01-18 17:10:51 -0800340 }
Wyatt Allen1b3eb9c2018-01-10 15:18:32 -0800341
342 Gerrit.Nav.navigateToDiff(this._change, this._commentSkips.next,
343 this._patchRange.patchNum, this._patchRange.basePatchNum);
Wyatt Allen1bc4f2f2017-01-18 17:10:51 -0800344 },
345
Kasper Nilssonef511942017-05-16 14:38:48 -0700346 _handleCKey(e) {
Andrew Bonventre4d22c7e2016-11-15 17:01:15 -0800347 if (this.shouldSuppressKeyboardShortcut(e)) { return; }
348 if (this.$.diff.isRangeSelected()) { return; }
Kasper Nilsson1ba850e2016-11-28 15:16:21 -0800349 if (this.modifierPressed(e)) { return; }
Andrew Bonventre4d22c7e2016-11-15 17:01:15 -0800350
351 e.preventDefault();
Kasper Nilssonef511942017-05-16 14:38:48 -0700352 const line = this.$.cursor.getTargetLineElement();
Andrew Bonventre4d22c7e2016-11-15 17:01:15 -0800353 if (line) {
354 this.$.diff.addDraftAtLine(line);
Andrew Bonventre78792e82016-03-04 17:48:22 -0500355 }
356 },
357
Kasper Nilssonef511942017-05-16 14:38:48 -0700358 _handleLeftBracketKey(e) {
Kasper Nilssoneb075312017-05-24 13:49:02 -0700359 // Check for meta key to avoid overriding native chrome shortcut.
Kasper Nilssonfa4b2fe2016-12-07 18:02:34 -0800360 if (this.shouldSuppressKeyboardShortcut(e) ||
Kasper Nilssoneb075312017-05-24 13:49:02 -0700361 this.getKeyboardEvent(e).metaKey) { return; }
Andrew Bonventre4d22c7e2016-11-15 17:01:15 -0800362
363 e.preventDefault();
364 this._navToFile(this._path, this._fileList, -1);
365 },
366
Kasper Nilssonef511942017-05-16 14:38:48 -0700367 _handleRightBracketKey(e) {
Kasper Nilssoneb075312017-05-24 13:49:02 -0700368 // Check for meta key to avoid overriding native chrome shortcut.
Kasper Nilssonfa4b2fe2016-12-07 18:02:34 -0800369 if (this.shouldSuppressKeyboardShortcut(e) ||
Kasper Nilssoneb075312017-05-24 13:49:02 -0700370 this.getKeyboardEvent(e).metaKey) { return; }
Andrew Bonventre4d22c7e2016-11-15 17:01:15 -0800371
372 e.preventDefault();
373 this._navToFile(this._path, this._fileList, 1);
374 },
375
Kasper Nilssonef511942017-05-16 14:38:48 -0700376 _handleNKey(e) {
Andrew Bonventre4d22c7e2016-11-15 17:01:15 -0800377 if (this.shouldSuppressKeyboardShortcut(e)) { return; }
378
379 e.preventDefault();
380 if (e.detail.keyboardEvent.shiftKey) {
381 this.$.cursor.moveToNextCommentThread();
382 } else {
Kasper Nilssonfa4b2fe2016-12-07 18:02:34 -0800383 if (this.modifierPressed(e)) { return; }
Andrew Bonventre4d22c7e2016-11-15 17:01:15 -0800384 this.$.cursor.moveToNextChunk();
385 }
386 },
387
Kasper Nilssonef511942017-05-16 14:38:48 -0700388 _handlePKey(e) {
Andrew Bonventre4d22c7e2016-11-15 17:01:15 -0800389 if (this.shouldSuppressKeyboardShortcut(e)) { return; }
390
391 e.preventDefault();
392 if (e.detail.keyboardEvent.shiftKey) {
393 this.$.cursor.moveToPreviousCommentThread();
394 } else {
Kasper Nilssonfa4b2fe2016-12-07 18:02:34 -0800395 if (this.modifierPressed(e)) { return; }
Andrew Bonventre4d22c7e2016-11-15 17:01:15 -0800396 this.$.cursor.moveToPreviousChunk();
397 }
398 },
399
Kasper Nilssonef511942017-05-16 14:38:48 -0700400 _handleAKey(e) {
Andrew Bonventre4d22c7e2016-11-15 17:01:15 -0800401 if (this.shouldSuppressKeyboardShortcut(e)) { return; }
402
403 if (e.detail.keyboardEvent.shiftKey) { // Hide left diff.
404 e.preventDefault();
405 this.$.diff.toggleLeftDiff();
406 return;
407 }
408
Kasper Nilssonfa4b2fe2016-12-07 18:02:34 -0800409 if (this.modifierPressed(e)) { return; }
410
Andrew Bonventre4d22c7e2016-11-15 17:01:15 -0800411 if (!this._loggedIn) { return; }
412
413 this.set('changeViewState.showReplyDialog', true);
414 e.preventDefault();
415 this._navToChangeView();
416 },
417
Kasper Nilssonef511942017-05-16 14:38:48 -0700418 _handleUKey(e) {
Kasper Nilssonfa4b2fe2016-12-07 18:02:34 -0800419 if (this.shouldSuppressKeyboardShortcut(e) ||
420 this.modifierPressed(e)) { return; }
Andrew Bonventre4d22c7e2016-11-15 17:01:15 -0800421
422 e.preventDefault();
423 this._navToChangeView();
424 },
425
Kasper Nilssonef511942017-05-16 14:38:48 -0700426 _handleCommaKey(e) {
Kasper Nilssonfa4b2fe2016-12-07 18:02:34 -0800427 if (this.shouldSuppressKeyboardShortcut(e) ||
428 this.modifierPressed(e)) { return; }
Andrew Bonventre4d22c7e2016-11-15 17:01:15 -0800429
430 e.preventDefault();
Becky Siegel7a454002017-04-19 12:06:43 -0700431 this.$.diffPreferences.open();
Andrew Bonventre4d22c7e2016-11-15 17:01:15 -0800432 },
433
Wyatt Allen61e414c2018-02-06 17:02:17 -0800434 _handleMKey(e) {
James Putman376b5e92018-01-13 20:55:22 -0700435 if (this.shouldSuppressKeyboardShortcut(e) ||
436 this.modifierPressed(e)) { return; }
437
438 e.preventDefault();
Wyatt Allen61e414c2018-02-06 17:02:17 -0800439 if (this._getDiffViewMode() === DiffViewMode.SIDE_BY_SIDE) {
Wyatt Allenffae7242018-02-14 15:58:17 -0800440 this.$.modeSelect.setMode(DiffViewMode.UNIFIED);
James Putman376b5e92018-01-13 20:55:22 -0700441 } else {
Wyatt Allenffae7242018-02-14 15:58:17 -0800442 this.$.modeSelect.setMode(DiffViewMode.SIDE_BY_SIDE);
James Putman376b5e92018-01-13 20:55:22 -0700443 }
444 },
445
Kasper Nilssonef511942017-05-16 14:38:48 -0700446 _navToChangeView() {
Andrew Bonventre4d22c7e2016-11-15 17:01:15 -0800447 if (!this._changeNum || !this._patchRange.patchNum) { return; }
Wyatt Allenc310f4f2017-07-05 21:26:33 -0700448 this._navigateToChange(
449 this._change,
Andrew Bonventre4d22c7e2016-11-15 17:01:15 -0800450 this._patchRange,
Wyatt Allenc310f4f2017-07-05 21:26:33 -0700451 this._change && this._change.revisions);
Paladox noned43abe92017-03-29 16:33:29 +0000452 },
453
Kasper Nilssonef511942017-05-16 14:38:48 -0700454 _navToFile(path, fileList, direction) {
Wyatt Allenc310f4f2017-07-05 21:26:33 -0700455 const newPath = this._getNavLinkPath(path, fileList, direction);
456 if (!newPath) { return; }
Andrew Bonventre78792e82016-03-04 17:48:22 -0500457
Wyatt Allenc310f4f2017-07-05 21:26:33 -0700458 if (newPath.up) {
459 this._navigateToChange(
460 this._change,
461 this._patchRange,
462 this._change && this._change.revisions);
463 return;
464 }
465
466 Gerrit.Nav.navigateToDiff(this._change, newPath.path,
467 this._patchRange.patchNum, this._patchRange.basePatchNum);
Andrew Bonventre04e57d62016-09-07 17:34:41 -0400468 },
469
470 /**
471 * @param {?string} path The path of the current file being shown.
Becky Siegel8d92d532017-08-11 16:32:47 -0700472 * @param {!Array<string>} fileList The list of files in this change and
Andrew Bonventre04e57d62016-09-07 17:34:41 -0400473 * patch range.
474 * @param {number} direction Either 1 (next file) or -1 (prev file).
475 * @param {(number|boolean)} opt_noUp Whether to return to the change view
476 * when advancing the file goes outside the bounds of fileList.
477 *
478 * @return {?string} The next URL when proceeding in the specified
479 * direction.
480 */
Wyatt Allenc310f4f2017-07-05 21:26:33 -0700481 _computeNavLinkURL(change, path, fileList, direction, opt_noUp) {
482 const newPath = this._getNavLinkPath(path, fileList, direction, opt_noUp);
483 if (!newPath) { return null; }
484
485 if (newPath.up) {
486 return this._getChangePath(
487 this._change,
488 this._patchRange,
489 this._change && this._change.revisions);
490 }
491 return this._getDiffUrl(this._change, this._patchRange, newPath.path);
492 },
493
494 /**
495 * Gives an object representing the target of navigating either left or
496 * right through the change. The resulting object will have one of the
497 * following forms:
498 * * {path: "<target file path>"} - When another file path should be the
499 * result of the navigation.
500 * * {up: true} - When the result of navigating should go back to the
501 * change view.
502 * * null - When no navigation is possible for the given direction.
503 *
504 * @param {?string} path The path of the current file being shown.
Becky Siegel8d92d532017-08-11 16:32:47 -0700505 * @param {!Array<string>} fileList The list of files in this change and
Wyatt Allenc310f4f2017-07-05 21:26:33 -0700506 * patch range.
507 * @param {number} direction Either 1 (next file) or -1 (prev file).
Becky Siegel8d92d532017-08-11 16:32:47 -0700508 * @param {?number|boolean=} opt_noUp Whether to return to the change view
Wyatt Allenc310f4f2017-07-05 21:26:33 -0700509 * when advancing the file goes outside the bounds of fileList.
Becky Siegel8d92d532017-08-11 16:32:47 -0700510 * @return {?Object}
Wyatt Allenc310f4f2017-07-05 21:26:33 -0700511 */
512 _getNavLinkPath(path, fileList, direction, opt_noUp) {
Andrew Bonventre04e57d62016-09-07 17:34:41 -0400513 if (!path || fileList.length === 0) { return null; }
514
Kasper Nilssonef511942017-05-16 14:38:48 -0700515 let idx = fileList.indexOf(path);
Kasper Nilssonde8dc082017-01-06 15:31:32 -0800516 if (idx === -1) {
Kasper Nilssonef511942017-05-16 14:38:48 -0700517 const file = direction > 0 ?
518 fileList[0] :
519 fileList[fileList.length - 1];
Wyatt Allenc310f4f2017-07-05 21:26:33 -0700520 return {path: file};
Kasper Nilssonde8dc082017-01-06 15:31:32 -0800521 }
Andrew Bonventre04e57d62016-09-07 17:34:41 -0400522
523 idx += direction;
524 // Redirect to the change view if opt_noUp isn’t truthy and idx falls
525 // outside the bounds of [0, fileList.length).
Andrew Bonventre78792e82016-03-04 17:48:22 -0500526 if (idx < 0 || idx > fileList.length - 1) {
Andrew Bonventre04e57d62016-09-07 17:34:41 -0400527 if (opt_noUp) { return null; }
Wyatt Allenc310f4f2017-07-05 21:26:33 -0700528 return {up: true};
Andrew Bonventre78792e82016-03-04 17:48:22 -0500529 }
Wyatt Allenc310f4f2017-07-05 21:26:33 -0700530
531 return {path: fileList[idx]};
Andrew Bonventre78792e82016-03-04 17:48:22 -0500532 },
533
Kasper Nilssonef511942017-05-16 14:38:48 -0700534 _paramsChanged(value) {
Kasper Nilsson3c2e1212017-07-17 14:12:16 -0700535 if (value.view !== Gerrit.Nav.View.DIFF) { return; }
Andrew Bonventre78792e82016-03-04 17:48:22 -0500536
Wyatt Allene515ff62018-01-19 17:54:50 -0800537 this.$.diff.lineOfInterest = this._getLineOfInterest(this.params);
Wyatt Allenfd6a9472017-08-28 16:42:40 -0700538 this._initCursor(this.params);
Andrew Bonventrec80291c2016-04-23 23:18:43 -0400539
Andrew Bonventre78792e82016-03-04 17:48:22 -0500540 this._changeNum = value.changeNum;
541 this._patchRange = {
542 patchNum: value.patchNum,
Wyatt Allendc8782d2017-07-26 09:32:03 -0700543 basePatchNum: value.basePatchNum || PARENT,
Andrew Bonventre78792e82016-03-04 17:48:22 -0500544 };
545 this._path = value.path;
546
Wyatt Allene9bd3e22017-07-26 09:44:27 -0700547 // NOTE: This may be called before attachment (e.g. while parentElement is
548 // null). Fire title-change in an async so that, if attachment to the DOM
549 // has been queued, the event can bubble up to the handler in gr-app.
Wyatt Allen68e1e212017-07-25 13:25:43 -0700550 this.async(() => {
551 this.fire('title-change',
Kasper Nilssonce67e2a2017-09-12 14:15:44 -0700552 {title: this.computeTruncatedPath(this._path)});
Wyatt Allen68e1e212017-07-25 13:25:43 -0700553 });
Andrew Bonventre78792e82016-03-04 17:48:22 -0500554
555 // When navigating away from the page, there is a possibility that the
556 // patch number is no longer a part of the URL (say when navigating to
557 // the top-level change info view) and therefore undefined in `params`.
558 if (!this._patchRange.patchNum) {
559 return;
560 }
561
Kasper Nilssonef511942017-05-16 14:38:48 -0700562 const promises = [];
Andrew Bonventrec80291c2016-04-23 23:18:43 -0400563
Viktar Donichb2198e82016-06-09 16:08:04 -0700564 this._localPrefs = this.$.storage.getPreferences();
Kasper Nilssonef511942017-05-16 14:38:48 -0700565 promises.push(this._getDiffPreferences().then(prefs => {
Andrew Bonventrec80291c2016-04-23 23:18:43 -0400566 this._prefs = prefs;
Kasper Nilssonef511942017-05-16 14:38:48 -0700567 }));
Andrew Bonventrec80291c2016-04-23 23:18:43 -0400568
Kasper Nilssonef511942017-05-16 14:38:48 -0700569 promises.push(this._getPreferences().then(prefs => {
Wyatt Allenf93f1c242016-05-05 16:53:38 -0700570 this._userPrefs = prefs;
Kasper Nilssonef511942017-05-16 14:38:48 -0700571 }));
Wyatt Allenf93f1c242016-05-05 16:53:38 -0700572
Viktar Donicha28dee062017-11-10 16:03:13 -0800573 promises.push(this._getChangeDetail(this._changeNum).then(change => {
574 let commit;
575 let baseCommit;
Thomas Shafer849c4462018-02-05 12:05:38 -0800576 for (const commitSha in change.revisions) {
577 if (!change.revisions.hasOwnProperty(commitSha)) continue;
578 const revision = change.revisions[commitSha];
579 const patchNum = revision._number.toString();
Viktar Donicha28dee062017-11-10 16:03:13 -0800580 if (patchNum === this._patchRange.patchNum) {
Thomas Shafer849c4462018-02-05 12:05:38 -0800581 commit = commitSha;
582 const commitObj = revision.commit || {};
583 const parents = commitObj.parents || [];
584 if (this._patchRange.basePatchNum === PARENT && parents.length) {
585 baseCommit = parents[parents.length - 1].commit;
586 }
Viktar Donicha28dee062017-11-10 16:03:13 -0800587 } else if (patchNum === this._patchRange.basePatchNum) {
Thomas Shafer849c4462018-02-05 12:05:38 -0800588 baseCommit = commitSha;
Viktar Donicha28dee062017-11-10 16:03:13 -0800589 }
590 }
591 this._commitRange = {commit, baseCommit};
592 }));
Andrew Bonventrec80291c2016-04-23 23:18:43 -0400593
Wyatt Allendc8782d2017-07-26 09:32:03 -0700594 promises.push(this._loadComments());
595
David Ostrovskye6a6f442017-04-25 23:48:05 +0200596 promises.push(this._getChangeEdit(this._changeNum));
597
Kasper Nilsson29b2ab42017-10-09 11:36:19 -0700598 this._loading = true;
David Ostrovskye6a6f442017-04-25 23:48:05 +0200599 Promise.all(promises).then(r => {
600 const edit = r[4];
601 if (edit) {
602 this.set('_change.revisions.' + edit.commit.commit, {
603 _number: this.EDIT_NAME,
604 basePatchNum: edit.base_patch_set_number,
605 commit: edit.commit,
606 });
607 }
Wyatt Allen1333e302017-02-10 15:12:52 -0800608 this._loading = false;
Wyatt Allendc8782d2017-07-26 09:32:03 -0700609 this.$.diff.comments = this._commentsForDiff;
Wyatt Allen1333e302017-02-10 15:12:52 -0800610 this.$.diff.reload();
Kasper Nilssonef511942017-05-16 14:38:48 -0700611 });
Andrew Bonventre78792e82016-03-04 17:48:22 -0500612 },
613
Kasper Nilsson143a4272017-07-12 12:47:14 -0700614 _changeViewStateChanged(changeViewState) {
Thomas Shafer88c17972017-06-26 15:13:03 -0700615 if (changeViewState.diffMode === null) {
616 // If screen size is small, always default to unified view.
617 this.$.restAPI.getPreferences().then(prefs => {
618 this.set('changeViewState.diffMode', prefs.default_diff_view);
619 });
620 }
621 },
622
Kasper Nilssonf428a232018-02-07 11:37:22 -0800623 _setReviewedObserver(_loggedIn, paramsRecord, _prefs) {
Kasper Nilssonb1e23072018-01-23 10:33:44 -0800624 const params = paramsRecord.base || {};
Kasper Nilssonf428a232018-02-07 11:37:22 -0800625 if (!_loggedIn || _prefs.manual_review) { return; }
626
627 if (params.view === Gerrit.Nav.View.DIFF) {
Thomas Shafer88c17972017-06-26 15:13:03 -0700628 this._setReviewed(true);
629 }
630 },
631
Wyatt Allenbdd4e342016-06-20 14:38:33 -0700632 /**
Wyatt Allenfd6a9472017-08-28 16:42:40 -0700633 * If the params specify a diff address then configure the diff cursor.
Wyatt Allenbdd4e342016-06-20 14:38:33 -0700634 */
Wyatt Allenfd6a9472017-08-28 16:42:40 -0700635 _initCursor(params) {
636 if (params.lineNum === undefined) { return; }
637 if (params.leftSide) {
Wyatt Allenbdd4e342016-06-20 14:38:33 -0700638 this.$.cursor.side = DiffSides.LEFT;
Wyatt Allenbdd4e342016-06-20 14:38:33 -0700639 } else {
640 this.$.cursor.side = DiffSides.RIGHT;
641 }
Wyatt Allenfd6a9472017-08-28 16:42:40 -0700642 this.$.cursor.initialLineNumber = params.lineNum;
Wyatt Allenbdd4e342016-06-20 14:38:33 -0700643 },
644
Wyatt Allene515ff62018-01-19 17:54:50 -0800645 _getLineOfInterest(params) {
646 // If there is a line number specified, pass it along to the diff so that
647 // it will not get collapsed.
648 if (!params.lineNum) { return null; }
649 return {number: params.lineNum, leftSide: params.leftSide};
650 },
651
Kasper Nilssonef511942017-05-16 14:38:48 -0700652 _pathChanged(path) {
Thomas Shafer88c17972017-06-26 15:13:03 -0700653 if (path) {
654 this.fire('title-change',
Kasper Nilssonce67e2a2017-09-12 14:15:44 -0700655 {title: this.computeTruncatedPath(path)});
Thomas Shafer88c17972017-06-26 15:13:03 -0700656 }
657
Andrew Bonventre78792e82016-03-04 17:48:22 -0500658 if (this._fileList.length == 0) { return; }
659
660 this.set('changeViewState.selectedFileIndex',
661 this._fileList.indexOf(path));
Andrew Bonventre78792e82016-03-04 17:48:22 -0500662 },
663
Wyatt Allenc310f4f2017-07-05 21:26:33 -0700664 _getDiffUrl(change, patchRange, path) {
665 return Gerrit.Nav.getUrlForDiff(change, path, patchRange.patchNum,
666 patchRange.basePatchNum);
Andrew Bonventre91c62932016-05-11 14:31:49 -0400667 },
668
Kasper Nilssonef511942017-05-16 14:38:48 -0700669 _patchRangeStr(patchRange) {
670 let patchStr = patchRange.patchNum;
Andrew Bonventre78792e82016-03-04 17:48:22 -0500671 if (patchRange.basePatchNum != null &&
Wyatt Allendc8782d2017-07-26 09:32:03 -0700672 patchRange.basePatchNum != PARENT) {
Andrew Bonventre78792e82016-03-04 17:48:22 -0500673 patchStr = patchRange.basePatchNum + '..' + patchRange.patchNum;
674 }
Andrew Bonventre91c62932016-05-11 14:31:49 -0400675 return patchStr;
Andrew Bonventre78792e82016-03-04 17:48:22 -0500676 },
677
Wyatt Allenc310f4f2017-07-05 21:26:33 -0700678 /**
679 * When the latest patch of the change is selected (and there is no base
680 * patch) then the patch range need not appear in the URL. Return a patch
681 * range object with undefined values when a range is not needed.
Becky Siegel8d92d532017-08-11 16:32:47 -0700682 *
683 * @param {!Object} patchRange
684 * @param {!Object} revisions
685 * @return {!Object}
Wyatt Allenc310f4f2017-07-05 21:26:33 -0700686 */
687 _getChangeUrlRange(patchRange, revisions) {
688 let patchNum = undefined;
689 let basePatchNum = undefined;
Kasper Nilssonef511942017-05-16 14:38:48 -0700690 let latestPatchNum = -1;
Wyatt Allenc310f4f2017-07-05 21:26:33 -0700691 for (const rev of Object.values(revisions || {})) {
Kasper Nilssonef511942017-05-16 14:38:48 -0700692 latestPatchNum = Math.max(latestPatchNum, rev._number);
Andrew Bonventre78792e82016-03-04 17:48:22 -0500693 }
Wyatt Allendc8782d2017-07-26 09:32:03 -0700694 if (patchRange.basePatchNum !== PARENT ||
Andrew Bonventre91c62932016-05-11 14:31:49 -0400695 parseInt(patchRange.patchNum, 10) !== latestPatchNum) {
Wyatt Allenc310f4f2017-07-05 21:26:33 -0700696 patchNum = patchRange.patchNum;
697 basePatchNum = patchRange.basePatchNum;
Andrew Bonventre78792e82016-03-04 17:48:22 -0500698 }
Wyatt Allenc310f4f2017-07-05 21:26:33 -0700699 return {patchNum, basePatchNum};
Andrew Bonventre78792e82016-03-04 17:48:22 -0500700 },
701
Wyatt Allenc310f4f2017-07-05 21:26:33 -0700702 _getChangePath(change, patchRange, revisions) {
703 const range = this._getChangeUrlRange(patchRange, revisions);
704 return Gerrit.Nav.getUrlForChange(change, range.patchNum,
705 range.basePatchNum);
706 },
707
708 _navigateToChange(change, patchRange, revisions) {
709 const range = this._getChangeUrlRange(patchRange, revisions);
710 Gerrit.Nav.navigateToChange(change, range.patchNum, range.basePatchNum);
711 },
712
713 _computeChangePath(change, patchRangeRecord, revisions) {
714 return this._getChangePath(change, patchRangeRecord.base, revisions);
Andrew Bonventre91c62932016-05-11 14:31:49 -0400715 },
716
Becky Siegel5946f952017-11-09 11:53:33 -0800717 _formatFilesForDropdown(fileList, patchNum, changeComments) {
Becky Siegelfde2da62017-11-07 15:49:55 -0800718 if (!fileList) { return; }
719 const dropdownContent = [];
720 for (const path of fileList) {
721 dropdownContent.push({
722 text: this.computeDisplayPath(path),
723 mobileText: this.computeTruncatedPath(path),
Becky Siegele53ca1c2017-11-13 16:23:08 -0800724 value: path,
Becky Siegel5946f952017-11-09 11:53:33 -0800725 bottomText: this._computeCommentString(changeComments, patchNum,
726 path),
Becky Siegelfde2da62017-11-07 15:49:55 -0800727 });
728 }
729 return dropdownContent;
Andrew Bonventre78792e82016-03-04 17:48:22 -0500730 },
731
Becky Siegel5946f952017-11-09 11:53:33 -0800732 _computeCommentString(changeComments, patchNum, path) {
733 const unresolvedCount = changeComments.computeUnresolvedNum(patchNum,
734 path);
735 const commentCount = changeComments.computeCommentCount(patchNum, path);
736 const commentString = GrCountStringFormatter.computePluralString(
737 commentCount, 'comment');
738 const unresolvedString = GrCountStringFormatter.computeString(
739 unresolvedCount, 'unresolved');
740
741 return commentString +
742 // Add a space if both comments and unresolved
743 (commentString && unresolvedString ? ', ' : '') +
744 // Add parentheses around unresolved if it exists.
745 (unresolvedString ? `${unresolvedString}` : '');
746 },
747
Kasper Nilssonef511942017-05-16 14:38:48 -0700748 _computePrefsButtonHidden(prefs, loggedIn) {
Andrew Bonventrec80291c2016-04-23 23:18:43 -0400749 return !loggedIn || !prefs;
750 },
751
Becky Siegelfde2da62017-11-07 15:49:55 -0800752 _handleFileChange(e) {
753 // This is when it gets set initially.
754 const path = e.detail.value;
755 if (path === this._path) {
756 return;
Andrew Bonventre78792e82016-03-04 17:48:22 -0500757 }
Becky Siegelfde2da62017-11-07 15:49:55 -0800758
759 Gerrit.Nav.navigateToDiff(this._change, path, this._patchRange.patchNum,
760 this._patchRange.basePatchNum);
Andrew Bonventre78792e82016-03-04 17:48:22 -0500761 },
762
Kasper Nilssonef511942017-05-16 14:38:48 -0700763 _handleFileTap(e) {
Becky Siegel03049072017-04-06 14:24:48 -0700764 // async is needed so that that the click event is fired before the
765 // dropdown closes (This was a bug for touch devices).
Kasper Nilssonef511942017-05-16 14:38:48 -0700766 this.async(() => {
Becky Siegel03049072017-04-06 14:24:48 -0700767 this.$.dropdown.close();
768 }, 1);
Andrew Bonventre78792e82016-03-04 17:48:22 -0500769 },
770
Becky Siegelaf950fd2017-10-12 11:35:18 -0700771 _handlePatchChange(e) {
772 const {basePatchNum, patchNum} = e.detail;
773 if (this.patchNumEquals(basePatchNum, this._patchRange.basePatchNum) &&
774 this.patchNumEquals(patchNum, this._patchRange.patchNum)) { return; }
Becky Siegel89fe0502017-09-12 16:54:19 -0700775 Gerrit.Nav.navigateToDiff(
Becky Siegelfd7c71f2017-09-26 09:59:33 -0700776 this._change, this._path, patchNum, basePatchNum);
Becky Siegel89fe0502017-09-12 16:54:19 -0700777 },
778
Kasper Nilssonef511942017-05-16 14:38:48 -0700779 _handlePrefsTap(e) {
Andrew Bonventrec80291c2016-04-23 23:18:43 -0400780 e.preventDefault();
Becky Siegel7a454002017-04-19 12:06:43 -0700781 this.$.diffPreferences.open();
Andrew Bonventrec80291c2016-04-23 23:18:43 -0400782 },
783
Kasper Nilssonef511942017-05-16 14:38:48 -0700784 _handlePrefsSave(e) {
Andrew Bonventrec80291c2016-04-23 23:18:43 -0400785 e.stopPropagation();
Kasper Nilssonef511942017-05-16 14:38:48 -0700786 const el = Polymer.dom(e).rootTarget;
Andrew Bonventrec80291c2016-04-23 23:18:43 -0400787 el.disabled = true;
Viktar Donich5008b442016-06-08 12:37:31 -0700788 this.$.storage.savePreferences(this._localPrefs);
Kasper Nilssonef511942017-05-16 14:38:48 -0700789 this._saveDiffPreferences().then(response => {
Andrew Bonventrec80291c2016-04-23 23:18:43 -0400790 el.disabled = false;
Andrew Bonventre8f231072016-05-02 15:59:59 -0400791 if (!response.ok) { return response; }
792
Andrew Bonventrec80291c2016-04-23 23:18:43 -0400793 this.$.prefsOverlay.close();
Kasper Nilssonef511942017-05-16 14:38:48 -0700794 }).catch(err => {
Andrew Bonventre8f231072016-05-02 15:59:59 -0400795 el.disabled = false;
Kasper Nilssonef511942017-05-16 14:38:48 -0700796 });
Andrew Bonventrec80291c2016-04-23 23:18:43 -0400797 },
798
Wyatt Allenf93f1c242016-05-05 16:53:38 -0700799 /**
800 * _getDiffViewMode: Get the diff view (side-by-side or unified) based on
801 * the current state.
802 *
803 * The expected behavior is to use the mode specified in the user's
Becky Siegel76ec5962016-12-09 16:58:31 -0800804 * preferences unless they have manually chosen the alternative view or they
805 * are on a mobile device. If the user navigates up to the change view, it
806 * should clear this choice and revert to the preference the next time a
807 * diff is viewed.
Wyatt Allenf93f1c242016-05-05 16:53:38 -0700808 *
809 * Use side-by-side if the user is not logged in.
810 *
Becky Siegel8d92d532017-08-11 16:32:47 -0700811 * @return {string}
Wyatt Allenf93f1c242016-05-05 16:53:38 -0700812 */
Kasper Nilssonef511942017-05-16 14:38:48 -0700813 _getDiffViewMode() {
Wyatt Allenf93f1c242016-05-05 16:53:38 -0700814 if (this.changeViewState.diffMode) {
815 return this.changeViewState.diffMode;
Becky Siegel76ec5962016-12-09 16:58:31 -0800816 } else if (this._userPrefs) {
Wyatt Allenffae7242018-02-14 15:58:17 -0800817 this.set('changeViewState.diffMode', this._userPrefs.default_diff_view);
818 return this._userPrefs.default_diff_view;
Becky Siegel76ec5962016-12-09 16:58:31 -0800819 } else {
820 return 'SIDE_BY_SIDE';
Wyatt Allenf93f1c242016-05-05 16:53:38 -0700821 }
Wyatt Allenf93f1c242016-05-05 16:53:38 -0700822 },
823
Wyatt Allenffae7242018-02-14 15:58:17 -0800824 _computeModeSelectHideClass(isImageDiff) {
825 return isImageDiff ? 'hide' : '';
Wyatt Allen88678da2016-05-23 17:18:43 -0700826 },
Wyatt Allena68b48e2016-06-20 14:02:42 -0700827
Kasper Nilssonef511942017-05-16 14:38:48 -0700828 _onLineSelected(e, detail) {
Wyatt Allena68b48e2016-06-20 14:02:42 -0700829 this.$.cursor.moveToLineNumber(detail.number, detail.side);
Wyatt Allenaea99742017-08-22 13:37:13 -0700830 if (!this._change) { return; }
831 const cursorAddress = this.$.cursor.getAddress();
Wyatt Allen1bd466a2017-09-15 11:55:35 -0700832 const number = cursorAddress ? cursorAddress.number : undefined;
833 const leftSide = cursorAddress ? cursorAddress.leftSide : undefined;
Wyatt Allenaea99742017-08-22 13:37:13 -0700834 const url = Gerrit.Nav.getUrlForDiffById(this._changeNum,
835 this._change.project, this._path, this._patchRange.patchNum,
Wyatt Allen1bd466a2017-09-15 11:55:35 -0700836 this._patchRange.basePatchNum, number, leftSide);
Wyatt Allenaea99742017-08-22 13:37:13 -0700837 history.replaceState(null, '', url);
Wyatt Allena68b48e2016-06-20 14:02:42 -0700838 },
Kasper Nilsson0deb7e32016-08-30 12:44:27 -0700839
Kasper Nilssonef511942017-05-16 14:38:48 -0700840 _computeDownloadLink(changeNum, patchRange, path) {
841 let url = this.changeBaseURL(changeNum, patchRange.patchNum);
Kasper Nilssonc59e880582016-10-21 11:01:08 -0700842 url += '/patch?zip&path=' + encodeURIComponent(path);
843 return url;
844 },
Wyatt Allen1bc4f2f2017-01-18 17:10:51 -0800845
Wyatt Allendc8782d2017-07-26 09:32:03 -0700846 _loadComments() {
Becky Siegel2033dfd2017-11-08 12:02:04 -0800847 return this.$.commentAPI.loadAll(this._changeNum).then(comments => {
848 this._changeComments = comments;
Becky Siegelc7f07dc2017-11-02 16:07:13 -0700849 this._commentMap = this._getPaths(this._patchRange);
Wyatt Allen1bc4f2f2017-01-18 17:10:51 -0800850
Becky Siegelc7f07dc2017-11-02 16:07:13 -0700851 this._commentsForDiff = this._getCommentsForPath(this._path,
Wyatt Allendc8782d2017-07-26 09:32:03 -0700852 this._patchRange, this._projectConfig);
Kasper Nilssonef511942017-05-16 14:38:48 -0700853 });
Wyatt Allen1bc4f2f2017-01-18 17:10:51 -0800854 },
855
Becky Siegelc7f07dc2017-11-02 16:07:13 -0700856 _getPaths(patchRange) {
857 return this._changeComments.getPaths(patchRange);
858 },
859
860 _getCommentsForPath(path, patchRange, projectConfig) {
Becky Siegel57e4fb32017-11-09 13:21:11 -0800861 return this._changeComments.getCommentsBySideForPath(path, patchRange,
Becky Siegelc7f07dc2017-11-02 16:07:13 -0700862 projectConfig);
863 },
864
Kasper Nilssonef511942017-05-16 14:38:48 -0700865 _getDiffDrafts() {
Wyatt Allenc61ba252017-07-31 18:43:21 -0700866 return this.$.restAPI.getDiffDrafts(this._changeNum);
Wyatt Allen1bc4f2f2017-01-18 17:10:51 -0800867 },
868
Kasper Nilssonef511942017-05-16 14:38:48 -0700869 _computeCommentSkips(commentMap, fileList, path) {
870 const skips = {previous: null, next: null};
Wyatt Allen1bc4f2f2017-01-18 17:10:51 -0800871 if (!fileList.length) { return skips; }
Kasper Nilssonef511942017-05-16 14:38:48 -0700872 const pathIndex = fileList.indexOf(path);
Wyatt Allen1bc4f2f2017-01-18 17:10:51 -0800873
874 // Scan backward for the previous file.
Kasper Nilssonef511942017-05-16 14:38:48 -0700875 for (let i = pathIndex - 1; i >= 0; i--) {
Wyatt Allen1bc4f2f2017-01-18 17:10:51 -0800876 if (commentMap[fileList[i]]) {
877 skips.previous = fileList[i];
878 break;
879 }
880 }
881
882 // Scan forward for the next file.
Kasper Nilssonef511942017-05-16 14:38:48 -0700883 for (let i = pathIndex + 1; i < fileList.length; i++) {
Wyatt Allen1bc4f2f2017-01-18 17:10:51 -0800884 if (commentMap[fileList[i]]) {
885 skips.next = fileList[i];
886 break;
887 }
888 }
889
890 return skips;
891 },
Viktar Donich168bbc92017-06-19 14:50:09 -0700892
893 _computeDiffClass(panelFloatingDisabled) {
894 if (panelFloatingDisabled) {
895 return 'noOverflow';
896 }
897 },
Kasper Nilsson5f1f0c62017-08-08 14:04:54 -0700898
899 /**
900 * @param {!Object} patchRangeRecord
901 */
Kasper Nilsson808838e2018-01-23 17:15:38 -0800902 _computeEditMode(patchRangeRecord) {
Kasper Nilsson5f1f0c62017-08-08 14:04:54 -0700903 const patchRange = patchRangeRecord.base || {};
904 return this.patchNumEquals(patchRange.patchNum, this.EDIT_NAME);
905 },
906
907 /**
Kasper Nilsson808838e2018-01-23 17:15:38 -0800908 * @param {boolean} editMode
Kasper Nilsson5f1f0c62017-08-08 14:04:54 -0700909 */
Kasper Nilsson808838e2018-01-23 17:15:38 -0800910 _computeContainerClass(editMode) {
911 return editMode ? 'editMode' : '';
Kasper Nilsson5f1f0c62017-08-08 14:04:54 -0700912 },
Wyatt Allened628d72017-09-14 09:45:50 -0700913
914 _computeBlameToggleLabel(loaded, loading) {
915 if (loaded) { return 'Hide blame'; }
916 return 'Show blame';
917 },
918
919 /**
920 * Load and display blame information if it has not already been loaded.
921 * Otherwise hide it.
922 */
923 _toggleBlame() {
924 if (this._isBlameLoaded) {
925 this.$.diff.clearBlame();
926 return;
927 }
928
929 this._isBlameLoading = true;
930 this.fire('show-alert', {message: MSG_LOADING_BLAME});
931 this.$.diff.loadBlame()
932 .then(() => {
933 this._isBlameLoading = false;
934 this.fire('show-alert', {message: MSG_LOADED_BLAME});
935 })
936 .catch(() => {
937 this._isBlameLoading = false;
938 });
939 },
940
941 _computeBlameLoaderClass(isImageDiff, supported) {
942 return !isImageDiff && supported ? 'show' : '';
943 },
Wyatt Allena744e232017-11-08 15:33:48 -0800944
945 _getRevisionInfo(change) {
946 return new Gerrit.RevisionInfo(change);
947 },
Viktar Donichc5069b12018-01-30 16:17:13 -0800948
949 _computeFileNum(file, files) {
950 return files.findIndex(({value}) => value === file) + 1;
951 },
952
953 _computeFileNumVisible(file, files) {
954 if (!files) { return 'hidden'; }
955 const fileNum = this._computeFileNum(file, files);
956 if (!isNaN(fileNum) && isFinite(fileNum) && fileNum > 0) {
957 return '';
958 } else {
959 return 'hidden';
960 }
961 },
Andrew Bonventre78792e82016-03-04 17:48:22 -0500962 });
963})();