diff --git a/src/browser/index.jsx b/src/browser/index.jsx index 60653f18..481ccdd7 100644 --- a/src/browser/index.jsx +++ b/src/browser/index.jsx @@ -25,7 +25,8 @@ var MainPage = React.createClass({ key: 0, unreadCounts: new Array(this.props.teams.length), mentionCounts: new Array(this.props.teams.length), - unreadAtActive: new Array(this.props.teams.length) + unreadAtActive: new Array(this.props.teams.length), + mentionAtActive: new Array(this.props.teams.length) }; }, componentDidMount: function() { @@ -60,11 +61,14 @@ var MainPage = React.createClass({ }); this.handleUnreadCountTotalChange(); }, - handleUnreadAtActiveChange: function(index, state) { + handleUnreadAtActiveChange: function(index, isUnread, isMentioned) { var unreadAtActive = this.state.unreadAtActive; - unreadAtActive[index] = state; + var mentionAtActive = this.state.mentionAtActive; + unreadAtActive[index] = isUnread; + mentionAtActive[index] = isMentioned; this.setState({ - unreadAtActive: unreadAtActive + unreadAtActive: unreadAtActive, + mentionAtActive: mentionAtActive }); this.handleUnreadCountTotalChange(); }, @@ -81,19 +85,24 @@ var MainPage = React.createClass({ var allMentionCount = this.state.mentionCounts.reduce(function(prev, curr) { return prev + curr; }, 0); + this.state.mentionAtActive.forEach(function(state) { + if (state) { + allMentionCount += 1; + } + }); this.props.onUnreadCountChange(allUnreadCount, allMentionCount); } }, - handleNotify: function(index) { + 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); + this.handleUnreadAtActiveChange(index, true, isMentioned); }, handleOnTeamFocused: function(index) { // Turn off the flag to indicate whether unread message of active channel contains at current tab. - this.handleUnreadAtActiveChange(index, false); + this.handleUnreadAtActiveChange(index, false, false); }, visibleStyle: function(visible) { @@ -124,8 +133,8 @@ var MainPage = React.createClass({ var handleUnreadCountChange = function(unreadCount, mentionCount) { thisObj.handleUnreadCountChange(index, unreadCount, mentionCount); }; - var handleNotify = function() { - thisObj.handleNotify(index); + var handleNotify = function(isMentioned) { + thisObj.handleNotify(index, isMentioned); }; var handleNotificationClick = function() { thisObj.handleSelect(index); @@ -197,9 +206,9 @@ var MattermostView = React.createClass({ } }, - handleNotify: function() { + handleNotify: function(isMentioned) { if (this.props.onNotify) { - this.props.onNotify(); + this.props.onNotify(isMentioned); } }, @@ -260,7 +269,8 @@ var MattermostView = React.createClass({ console.log(event.args[0]); break; case 'onActiveChannelNotify': - thisObj.handleNotify(); + var isMentioned = event.args[0]; + thisObj.handleNotify(isMentioned); break; } }); diff --git a/src/browser/webview/mattermost.js b/src/browser/webview/mattermost.js index 9dcb088b..ade81305 100644 --- a/src/browser/webview/mattermost.js +++ b/src/browser/webview/mattermost.js @@ -24,25 +24,6 @@ var unreadCountTimer = setInterval(function() { } } - // unreadCount for active channel - var newSeparators = document.getElementsByClassName('new-separator'); - var post; - for (var i = 0; i < newSeparators.length; i++) { - if (newSeparators[i].offsetParent !== null) { - post = newSeparators[i]; - } - } - // mentionCount for active channel - if (post != null) { - while (post = post.nextSibling) { - var highlight = post.getElementsByClassName('mention-highlight'); - if (highlight.length != 0 && highlight[0].offsetHeight != null) { - mentionCount++; - break; - } - } - } - if (this.unreadCount != unreadCount || this.mentionCount != mentionCount) { ipc.sendToHost('onUnreadCountChange', unreadCount, mentionCount); } @@ -80,6 +61,8 @@ function overrideNotificationWithBalloon() { Notification.prototype.close = function() {}; }; +var lastUnread = {}; + // Show window even if it is hidden/minimized when notification is clicked. function overrideNotification() { Notification = function(title, options) { @@ -89,8 +72,57 @@ function overrideNotification() { var activeChannel = document.querySelector('.active .sidebar-channel').text; console.log(activeChannel); console.log(title); - if (activeChannel === title) { - ipc.sendToHost('onActiveChannelNotify'); + + // 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) {