blob: 0d58d96117b59cf0cf3066a2b218fd3f2807ddbf [file] [log] [blame]
// Copyright (C) 2016 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
(function() {
'use strict';
var MAX_INITIAL_SHOWN_MESSAGES = 20;
var MESSAGES_INCREMENT = 5;
var ReportingEvent = {
SHOW_ALL: 'show-all-messages',
SHOW_MORE: 'show-more-messages',
};
Polymer({
is: 'gr-messages-list',
properties: {
changeNum: Number,
messages: {
type: Array,
value: function() { return []; },
},
reviewerUpdates: {
type: Array,
value: function() { return []; },
},
comments: Object,
projectConfig: Object,
showReplyButtons: {
type: Boolean,
value: false,
},
_expanded: {
type: Boolean,
value: false,
observer: '_expandedChanged',
},
_hideAutomated: {
type: Boolean,
value: false,
},
/**
* The messages after processing and including merged reviewer updates.
*/
_processedMessages: {
type: Array,
computed: '_computeItems(messages, reviewerUpdates)',
observer: '_processedMessagesChanged',
},
/**
* The subset of _processedMessages that is visible to the user.
*/
_visibleMessages: {
type: Array,
value: function() { return []; },
},
},
scrollToMessage: function(messageID) {
var el = this.$$('[data-message-id="' + messageID + '"]');
// If the message is hidden, expand the hidden messages back to that
// point.
if (!el) {
for (var index = 0; index < this._processedMessages.length; index++) {
if (this._processedMessages[index].id === messageID) {
break;
}
}
if (index === this._processedMessages.length) { return; }
var newMessages = this._processedMessages.slice(index,
-this._visibleMessages.length);
// Add newMessages to the beginning of _visibleMessages.
this.splice.apply(this, ['_visibleMessages', 0, 0].concat(newMessages));
// Allow the dom-repeat to stamp.
Polymer.dom.flush();
el = this.$$('[data-message-id="' + messageID + '"]');
}
el.set('message.expanded', true);
var top = el.offsetTop;
for (var offsetParent = el.offsetParent;
offsetParent;
offsetParent = offsetParent.offsetParent) {
top += offsetParent.offsetTop;
}
window.scrollTo(0, top);
this._highlightEl(el);
},
_isAutomated: function(message) {
return !!(message.reviewer ||
(message.tag && message.tag.indexOf('autogenerated') === 0));
},
_computeItems: function(messages, reviewerUpdates) {
messages = messages || [];
reviewerUpdates = reviewerUpdates || [];
var mi = 0;
var ri = 0;
var result = [];
var mDate;
var rDate;
for (var i = 0; i < messages.length; i++) {
messages[i]._index = i;
}
while (mi < messages.length || ri < reviewerUpdates.length) {
if (mi >= messages.length) {
result = result.concat(reviewerUpdates.slice(ri));
break;
}
if (ri >= reviewerUpdates.length) {
result = result.concat(messages.slice(mi));
break;
}
mDate = mDate || util.parseDate(messages[mi].date);
rDate = rDate || util.parseDate(reviewerUpdates[ri].date);
if (rDate < mDate) {
result.push(reviewerUpdates[ri++]);
rDate = null;
} else {
result.push(messages[mi++]);
mDate = null;
}
}
return result;
},
_expandedChanged: function(exp) {
for (var i = 0; i < this._processedMessages.length; i++) {
this._processedMessages[i].expanded = exp;
if (i < this._visibleMessages.length) {
this.set(['_visibleMessages', i, 'expanded'], exp);
}
}
},
_highlightEl: function(el) {
var highlightedEls =
Polymer.dom(this.root).querySelectorAll('.highlighted');
for (var i = 0; i < highlightedEls.length; i++) {
highlightedEls[i].classList.remove('highlighted');
}
function handleAnimationEnd() {
el.removeEventListener('animationend', handleAnimationEnd);
el.classList.remove('highlighted');
}
el.addEventListener('animationend', handleAnimationEnd);
el.classList.add('highlighted');
},
/**
* @param {boolean} expand
*/
handleExpandCollapse: function(expand) {
this._expanded = expand;
},
_handleExpandCollapseTap: function(e) {
e.preventDefault();
this.handleExpandCollapse(!this._expanded);
},
_handleAutomatedMessageToggleTap: function(e) {
e.preventDefault();
this._hideAutomated = !this._hideAutomated;
},
_handleScrollTo: function(e) {
this.scrollToMessage(e.detail.message.id);
},
_hasAutomatedMessages: function(messages) {
for (var i = 0; messages && i < messages.length; i++) {
if (this._isAutomated(messages[i])) {
return true;
}
}
return false;
},
_computeExpandCollapseMessage: function(expanded) {
return expanded ? 'Collapse all' : 'Expand all';
},
_computeAutomatedToggleText: function(hideAutomated) {
return hideAutomated ? 'Show all messages' : 'Show comments only';
},
/**
* Computes message author's file comments for change's message.
* Method uses this.messages to find next message and relies on messages
* to be sorted by date field descending.
* @param {!Object} comments Hash of arrays of comments, filename as key.
* @param {!Object} message
* @return {!Object} Hash of arrays of comments, filename as key.
*/
_computeCommentsForMessage: function(comments, message) {
if (message._index === undefined || !comments || !this.messages) {
return [];
}
var messages = this.messages || [];
var index = message._index;
var authorId = message.author && message.author._account_id;
var mDate = util.parseDate(message.date).getTime();
// NB: Messages array has oldest messages first.
var nextMDate;
if (index > 0) {
for (var i = index - 1; i >= 0; i--) {
if (messages[i] && messages[i].author &&
messages[i].author._account_id === authorId) {
nextMDate = util.parseDate(messages[i].date).getTime();
break;
}
}
}
var msgComments = {};
for (var file in comments) {
var fileComments = comments[file];
for (var i = 0; i < fileComments.length; i++) {
if (fileComments[i].author &&
fileComments[i].author._account_id !== authorId) {
continue;
}
var cDate = util.parseDate(fileComments[i].updated).getTime();
if (cDate <= mDate) {
if (nextMDate && cDate <= nextMDate) {
continue;
}
msgComments[file] = msgComments[file] || [];
msgComments[file].push(fileComments[i]);
}
}
}
return msgComments;
},
/**
* Returns the number of messages to splice to the beginning of
* _visibleMessages. This is the minimum of the total number of messages
* remaining in the list and the number of messages needed to display five
* more visible messages in the list.
*/
_getDelta: function(visibleMessages, messages, hideAutomated) {
var delta = MESSAGES_INCREMENT;
var msgsRemaining = messages.length - visibleMessages.length;
if (hideAutomated) {
var counter = 0;
var i;
for (i = msgsRemaining; i > 0 && counter < MESSAGES_INCREMENT; i--) {
if (!this._isAutomated(messages[i - 1])) { counter++; }
}
delta = msgsRemaining - i;
}
return Math.min(msgsRemaining, delta);
},
/**
* Gets the number of messages that would be visible, but do not currently
* exist in _visibleMessages.
*/
_numRemaining: function(visibleMessages, messages, hideAutomated) {
if (hideAutomated) {
return this._getHumanMessages(messages).length -
this._getHumanMessages(visibleMessages).length;
}
return messages.length - visibleMessages.length;
},
_computeIncrementText: function(visibleMessages, messages, hideAutomated) {
var delta = this._getDelta(visibleMessages, messages, hideAutomated);
delta = Math.min(
this._numRemaining(visibleMessages, messages, hideAutomated), delta);
return 'Show ' + Math.min(MESSAGES_INCREMENT, delta) + ' more';
},
_getHumanMessages: function(messages) {
return messages.filter(function(msg) {
return !this._isAutomated(msg);
}.bind(this));
},
_computeShowHideTextHidden: function(visibleMessages, messages,
hideAutomated) {
if (hideAutomated) {
messages = this._getHumanMessages(messages);
visibleMessages = this._getHumanMessages(visibleMessages);
}
return visibleMessages.length >= messages.length;
},
_handleShowAllTap: function() {
this._visibleMessages = this._processedMessages;
this.$.reporting.reportInteraction(ReportingEvent.SHOW_ALL);
},
_handleIncrementShownMessages: function() {
var delta = this._getDelta(this._visibleMessages, this._processedMessages,
this._hideAutomated);
var len = this._visibleMessages.length;
var newMessages = this._processedMessages.slice(-(len + delta), -len);
// Add newMessages to the beginning of _visibleMessages
this.splice.apply(this, ['_visibleMessages', 0, 0].concat(newMessages));
this.$.reporting.reportInteraction(ReportingEvent.SHOW_MORE);
},
_processedMessagesChanged: function(messages) {
this._visibleMessages = messages.slice(-MAX_INITIAL_SHOWN_MESSAGES);
},
_computeNumMessagesText: function(visibleMessages, messages,
hideAutomated) {
var total = this._numRemaining(visibleMessages, messages, hideAutomated);
return total === 1 ? 'Show 1 message' : 'Show all ' + total + ' messages';
},
});
})();