* refactoring
* bugfix: Post to active channel/DM with mention when window isn't focused, I expect count badge appear but unread badge appear.
This commit is contained in:
parent
95f393dc63
commit
f69f1f6016
|
@ -50,22 +50,31 @@ var MainPage = React.createClass({
|
||||||
});
|
});
|
||||||
this.handleOnTeamFocused(key);
|
this.handleOnTeamFocused(key);
|
||||||
},
|
},
|
||||||
handleUnreadCountChange: function(index, unreadCount, mentionCount) {
|
handleUnreadCountChange: function(index, unreadCount, mentionCount, isUnread, isMentioned) {
|
||||||
var unreadCounts = this.state.unreadCounts;
|
var unreadCounts = this.state.unreadCounts;
|
||||||
var mentionCounts = this.state.mentionCounts;
|
var mentionCounts = this.state.mentionCounts;
|
||||||
|
var unreadAtActive = this.state.unreadAtActive;
|
||||||
|
var mentionAtActive = this.state.mentionAtActive;
|
||||||
unreadCounts[index] = unreadCount;
|
unreadCounts[index] = unreadCount;
|
||||||
mentionCounts[index] = mentionCount;
|
mentionCounts[index] = mentionCount;
|
||||||
|
// Never turn on the unreadAtActive flag at current focused tab.
|
||||||
|
if (this.state.key !== index || !remote.getCurrentWindow().isFocused()) {
|
||||||
|
unreadAtActive[index] = unreadAtActive[index] || isUnread;
|
||||||
|
mentionAtActive[index] = mentionAtActive[index] || isMentioned;
|
||||||
|
}
|
||||||
this.setState({
|
this.setState({
|
||||||
unreadCounts: unreadCounts,
|
unreadCounts: unreadCounts,
|
||||||
mentionCounts: mentionCounts
|
mentionCounts: mentionCounts,
|
||||||
|
unreadAtActive: unreadAtActive,
|
||||||
|
mentionAtActive: mentionAtActive
|
||||||
});
|
});
|
||||||
this.handleUnreadCountTotalChange();
|
this.handleUnreadCountTotalChange();
|
||||||
},
|
},
|
||||||
handleUnreadAtActiveChange: function(index, isUnread, isMentioned) {
|
markReadAtActive: function(index) {
|
||||||
var unreadAtActive = this.state.unreadAtActive;
|
var unreadAtActive = this.state.unreadAtActive;
|
||||||
var mentionAtActive = this.state.mentionAtActive;
|
var mentionAtActive = this.state.mentionAtActive;
|
||||||
unreadAtActive[index] = isUnread;
|
unreadAtActive[index] = false;
|
||||||
mentionAtActive[index] = isMentioned;
|
mentionAtActive[index] = false;
|
||||||
this.setState({
|
this.setState({
|
||||||
unreadAtActive: unreadAtActive,
|
unreadAtActive: unreadAtActive,
|
||||||
mentionAtActive: mentionAtActive
|
mentionAtActive: mentionAtActive
|
||||||
|
@ -93,16 +102,9 @@ var MainPage = React.createClass({
|
||||||
this.props.onUnreadCountChange(allUnreadCount, allMentionCount);
|
this.props.onUnreadCountChange(allUnreadCount, allMentionCount);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
handleNotify: function(index, isMentioned) {
|
|
||||||
// Never turn on the unreadAtActive flag at current focused tab.
|
|
||||||
if (this.state.key === index && remote.getCurrentWindow().isFocused()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.handleUnreadAtActiveChange(index, true, isMentioned);
|
|
||||||
},
|
|
||||||
handleOnTeamFocused: function(index) {
|
handleOnTeamFocused: function(index) {
|
||||||
// Turn off the flag to indicate whether unread message of active channel contains at current tab.
|
// Turn off the flag to indicate whether unread message of active channel contains at current tab.
|
||||||
this.handleUnreadAtActiveChange(index, false, false);
|
this.markReadAtActive(index);
|
||||||
},
|
},
|
||||||
|
|
||||||
visibleStyle: function(visible) {
|
visibleStyle: function(visible) {
|
||||||
|
@ -123,24 +125,21 @@ var MainPage = React.createClass({
|
||||||
if (this.props.teams.length > 1) {
|
if (this.props.teams.length > 1) {
|
||||||
tabs_row = (
|
tabs_row = (
|
||||||
<Row>
|
<Row>
|
||||||
<TabBar id="tabBar" teams={ this.props.teams } unreadCounts={ this.state.unreadCounts } mentionCounts={ this.state.mentionCounts } unreadAtActive={ this.state.unreadAtActive } activeKey={ this.state.key }
|
<TabBar id="tabBar" teams={ this.props.teams } unreadCounts={ this.state.unreadCounts } mentionCounts={ this.state.mentionCounts } unreadAtActive={ this.state.unreadAtActive } mentionAtActive={ this.state.mentionAtActive }
|
||||||
onSelect={ this.handleSelect }></TabBar>
|
activeKey={ this.state.key } onSelect={ this.handleSelect }></TabBar>
|
||||||
</Row>
|
</Row>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
var views = this.props.teams.map(function(team, index) {
|
var views = this.props.teams.map(function(team, index) {
|
||||||
var handleUnreadCountChange = function(unreadCount, mentionCount) {
|
var handleUnreadCountChange = function(unreadCount, mentionCount, isUnread, isMentioned) {
|
||||||
thisObj.handleUnreadCountChange(index, unreadCount, mentionCount);
|
thisObj.handleUnreadCountChange(index, unreadCount, mentionCount, isUnread, isMentioned);
|
||||||
};
|
|
||||||
var handleNotify = function(isMentioned) {
|
|
||||||
thisObj.handleNotify(index, isMentioned);
|
|
||||||
};
|
};
|
||||||
var handleNotificationClick = function() {
|
var handleNotificationClick = function() {
|
||||||
thisObj.handleSelect(index);
|
thisObj.handleSelect(index);
|
||||||
}
|
}
|
||||||
return (<MattermostView id={ 'mattermostView' + index } style={ thisObj.visibleStyle(thisObj.state.key === index) } src={ team.url } onUnreadCountChange={ handleUnreadCountChange } onNotify={ handleNotify }
|
return (<MattermostView id={ 'mattermostView' + index } style={ thisObj.visibleStyle(thisObj.state.key === index) } src={ team.url } onUnreadCountChange={ handleUnreadCountChange } onNotificationClick={ handleNotificationClick }
|
||||||
onNotificationClick={ handleNotificationClick } />)
|
/>)
|
||||||
});
|
});
|
||||||
var views_row = (<Row>
|
var views_row = (<Row>
|
||||||
{ views }
|
{ views }
|
||||||
|
@ -158,7 +157,6 @@ var TabBar = React.createClass({
|
||||||
render: function() {
|
render: function() {
|
||||||
var thisObj = this;
|
var thisObj = this;
|
||||||
var tabs = this.props.teams.map(function(team, index) {
|
var tabs = this.props.teams.map(function(team, index) {
|
||||||
var badge;
|
|
||||||
var unreadCount = 0;
|
var unreadCount = 0;
|
||||||
if (thisObj.props.unreadCounts[index] > 0) {
|
if (thisObj.props.unreadCounts[index] > 0) {
|
||||||
unreadCount = thisObj.props.unreadCounts[index];
|
unreadCount = thisObj.props.unreadCounts[index];
|
||||||
|
@ -166,9 +164,19 @@ var TabBar = React.createClass({
|
||||||
if (thisObj.props.unreadAtActive[index]) {
|
if (thisObj.props.unreadAtActive[index]) {
|
||||||
unreadCount += 1;
|
unreadCount += 1;
|
||||||
}
|
}
|
||||||
if (thisObj.props.mentionCounts[index] != 0) {
|
|
||||||
|
var mentionCount = 0;
|
||||||
|
if (thisObj.props.mentionCounts[index] > 0) {
|
||||||
|
mentionCount = thisObj.props.mentionCounts[index];
|
||||||
|
}
|
||||||
|
if (thisObj.props.mentionAtActive[index] === true) {
|
||||||
|
mentionCount += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
var badge;
|
||||||
|
if (mentionCount != 0) {
|
||||||
badge = (<Badge>
|
badge = (<Badge>
|
||||||
{ thisObj.props.mentionCounts[index] }
|
{ mentionCount }
|
||||||
</Badge>);
|
</Badge>);
|
||||||
} else if (unreadCount > 0) {
|
} else if (unreadCount > 0) {
|
||||||
badge = (<Badge>
|
badge = (<Badge>
|
||||||
|
@ -192,23 +200,11 @@ var TabBar = React.createClass({
|
||||||
var MattermostView = React.createClass({
|
var MattermostView = React.createClass({
|
||||||
getInitialState: function() {
|
getInitialState: function() {
|
||||||
return {
|
return {
|
||||||
unreadCount: 0,
|
|
||||||
mentionCount: 0
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
handleUnreadCountChange: function(unreadCount, mentionCount) {
|
handleUnreadCountChange: function(unreadCount, mentionCount, isUnread, isMentioned) {
|
||||||
this.setState({
|
|
||||||
unreadCount: unreadCount,
|
|
||||||
mentionCount: mentionCount
|
|
||||||
});
|
|
||||||
if (this.props.onUnreadCountChange) {
|
if (this.props.onUnreadCountChange) {
|
||||||
this.props.onUnreadCountChange(unreadCount, mentionCount);
|
this.props.onUnreadCountChange(unreadCount, mentionCount, isUnread, isMentioned);
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
handleNotify: function(isMentioned) {
|
|
||||||
if (this.props.onNotify) {
|
|
||||||
this.props.onNotify(isMentioned);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -260,7 +256,10 @@ var MattermostView = React.createClass({
|
||||||
case 'onUnreadCountChange':
|
case 'onUnreadCountChange':
|
||||||
var unreadCount = event.args[0];
|
var unreadCount = event.args[0];
|
||||||
var mentionCount = event.args[1];
|
var mentionCount = event.args[1];
|
||||||
thisObj.handleUnreadCountChange(unreadCount, mentionCount);
|
// isUnread and isMentioned is pulse flag.
|
||||||
|
var isUnread = event.args[2];
|
||||||
|
var isMentioned = event.args[3];
|
||||||
|
thisObj.handleUnreadCountChange(unreadCount, mentionCount, isUnread, isMentioned);
|
||||||
break;
|
break;
|
||||||
case 'onNotificationClick':
|
case 'onNotificationClick':
|
||||||
thisObj.props.onNotificationClick();
|
thisObj.props.onNotificationClick();
|
||||||
|
@ -268,10 +267,6 @@ var MattermostView = React.createClass({
|
||||||
case 'console':
|
case 'console':
|
||||||
console.log(event.args[0]);
|
console.log(event.args[0]);
|
||||||
break;
|
break;
|
||||||
case 'onActiveChannelNotify':
|
|
||||||
var isMentioned = event.args[0];
|
|
||||||
thisObj.handleNotify(isMentioned);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -19,18 +19,71 @@ var unreadCountTimer = setInterval(function() {
|
||||||
var elem = document.getElementsByClassName('badge')
|
var elem = document.getElementsByClassName('badge')
|
||||||
var mentionCount = 0;
|
var mentionCount = 0;
|
||||||
for (var i = 0; i < elem.length; i++) {
|
for (var i = 0; i < elem.length; i++) {
|
||||||
if (elem[i].offsetHeight != 0) {
|
if (isElementVisible(elem[i])) {
|
||||||
mentionCount++;
|
mentionCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.unreadCount != unreadCount || this.mentionCount != mentionCount) {
|
var postAttrName = 'data-reactid';
|
||||||
ipc.sendToHost('onUnreadCountChange', unreadCount, mentionCount);
|
var lastPostElem = document.querySelector('div[' + postAttrName + '="' + lastCheckedPost.reactId + '"]');
|
||||||
|
var isUnread = false;
|
||||||
|
var isMentioned = false;
|
||||||
|
if (lastPostElem === null || !isElementVisible(lastPostElem)) {
|
||||||
|
// When load channel or change channel, lastCheckedPost.reactId is invalid.
|
||||||
|
// So we get latest post and save lastCheckedPost.
|
||||||
|
|
||||||
|
// find active post-list.
|
||||||
|
var postLists = document.querySelectorAll('div.post-list__content');
|
||||||
|
var post;
|
||||||
|
for (var i = 0; i < postLists.length; i++) {
|
||||||
|
if (isElementVisible(postLists[i])) {
|
||||||
|
post = postLists[i].children[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// find latest post and save.
|
||||||
|
while (post = post.nextSibling) {
|
||||||
|
if (post.nextSibling === null) {
|
||||||
|
if (post.getAttribute(postAttrName) !== null) {
|
||||||
|
lastCheckedPost.reactId = post.getAttribute(postAttrName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (lastPostElem !== null) {
|
||||||
|
var newPostElem = lastPostElem;
|
||||||
|
while (newPostElem = newPostElem.nextSibling) {
|
||||||
|
lastCheckedPost.reactId = newPostElem.getAttribute(postAttrName);
|
||||||
|
isUnread = true;
|
||||||
|
var activeChannel = document.querySelector('.active .sidebar-channel');
|
||||||
|
var closeButton = activeChannel.getElementsByClassName('btn-close');
|
||||||
|
if (closeButton.length === 1 && closeButton[0].getAttribute('aria-describedby') === 'remove-dm-tooltip') {
|
||||||
|
// If active channel is DM, all posts is treated as menion.
|
||||||
|
isMentioned = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// If active channel is public/private channel, only mentioned post is treated as mention.
|
||||||
|
var highlight = newPostElem.getElementsByClassName('mention-highlight');
|
||||||
|
if (highlight.length != 0 && isElementVisible(highlight[0])) {
|
||||||
|
isMentioned = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.unreadCount != unreadCount || this.mentionCount != mentionCount || isUnread || isMentioned) {
|
||||||
|
ipc.sendToHost('onUnreadCountChange', unreadCount, mentionCount, isUnread, isMentioned);
|
||||||
}
|
}
|
||||||
this.unreadCount = unreadCount;
|
this.unreadCount = unreadCount;
|
||||||
this.mentionCount = mentionCount;
|
this.mentionCount = mentionCount;
|
||||||
}, 1000);
|
}, 1000);
|
||||||
|
|
||||||
|
function isElementVisible(elem) {
|
||||||
|
return elem.offsetHeight !== 0;
|
||||||
|
}
|
||||||
|
|
||||||
// On Windows 8.1 and Windows 8, a shortcut with a Application User Model ID must be installed to the Start screen.
|
// On Windows 8.1 and Windows 8, a shortcut with a Application User Model ID must be installed to the Start screen.
|
||||||
// In current version, use tray balloon for notification
|
// In current version, use tray balloon for notification
|
||||||
function isLowerThanOrEqualWindows8_1() {
|
function isLowerThanOrEqualWindows8_1() {
|
||||||
|
@ -48,12 +101,6 @@ function overrideNotificationWithBalloon() {
|
||||||
title: title,
|
title: title,
|
||||||
options: options
|
options: options
|
||||||
});
|
});
|
||||||
|
|
||||||
// Send notification event at active channel.
|
|
||||||
var activeChannel = document.querySelector('.active .sidebar-channel').text;
|
|
||||||
if (activeChannel === title) {
|
|
||||||
ipc.sendToHost('onActiveChannelNotify');
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
Notification.requestPermission = function(callback) {
|
Notification.requestPermission = function(callback) {
|
||||||
callback('granted');
|
callback('granted');
|
||||||
|
@ -61,69 +108,14 @@ function overrideNotificationWithBalloon() {
|
||||||
Notification.prototype.close = function() {};
|
Notification.prototype.close = function() {};
|
||||||
};
|
};
|
||||||
|
|
||||||
var lastUnread = {};
|
var lastCheckedPost = {
|
||||||
|
reactId: null
|
||||||
|
};
|
||||||
|
|
||||||
// Show window even if it is hidden/minimized when notification is clicked.
|
// Show window even if it is hidden/minimized when notification is clicked.
|
||||||
function overrideNotification() {
|
function overrideNotification() {
|
||||||
Notification = function(title, options) {
|
Notification = function(title, options) {
|
||||||
this.notification = new NativeNotification(title, options);
|
this.notification = new NativeNotification(title, options);
|
||||||
|
|
||||||
// Send notification event at active channel.
|
|
||||||
var activeChannel = document.querySelector('.active .sidebar-channel').text;
|
|
||||||
console.log(activeChannel);
|
|
||||||
console.log(title);
|
|
||||||
|
|
||||||
// mentionCount for active channel
|
|
||||||
var newSeparators = document.getElementsByClassName('new-separator');
|
|
||||||
var post;
|
|
||||||
var isMentioned = false;
|
|
||||||
// Skip until real new-separator appear.
|
|
||||||
for (var i = 0; i < newSeparators.length; i++) {
|
|
||||||
if (newSeparators[i].offsetParent !== null) {
|
|
||||||
post = newSeparators[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If active channel is DM, all posts is treated as menion.
|
|
||||||
if (activeChannel === title + "×") {
|
|
||||||
isMentioned = true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// If active channel is CHANNEL, only .mention-highlight post is treated as mention.
|
|
||||||
if (post != null) {
|
|
||||||
// Skip posts until last unread.
|
|
||||||
if (activeChannel === title && lastUnread.channel === title && lastUnread.post !== null) {
|
|
||||||
var firstPost = post;
|
|
||||||
while (post = post.nextSibling) {
|
|
||||||
if (lastUnread.post === post.getAttribute('data-reactid')) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Because last unread post not found, set first post.
|
|
||||||
if (post === null) {
|
|
||||||
post = firstPost;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while (post = post.nextSibling) {
|
|
||||||
var highlight = post.getElementsByClassName('mention-highlight');
|
|
||||||
if (highlight.length != 0 && highlight[0].offsetHeight != null) {
|
|
||||||
isMentioned = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remember last unread post.
|
|
||||||
if (post.nextSibling === null) {
|
|
||||||
lastUnread.post = post.getAttribute('data-reactid');
|
|
||||||
lastUnread.channel = title;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Note: DM title is "{username}×". CHANNEL title is "{channel_title}".
|
|
||||||
if (activeChannel === title || activeChannel === title + "×") {
|
|
||||||
ipc.sendToHost('onActiveChannelNotify', isMentioned);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
Notification.requestPermission = function(callback) {
|
Notification.requestPermission = function(callback) {
|
||||||
callback('granted');
|
callback('granted');
|
||||||
|
|
Loading…
Reference in a new issue