diff --git a/package.json b/package.json index ac72744af4..4453e7f65c 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ }, "dependencies": { "classnames": "^2.1.2", + "favico.js": "^0.3.10", "filesize": "^3.1.2", "flux": "^2.0.3", "glob": "^5.0.14", diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index e5a98631d3..799cd58d93 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -16,6 +16,7 @@ limitations under the License. var React = require('react'); var Matrix = require("matrix-js-sdk"); var url = require('url'); +var Favico = require('favico.js'); var MatrixClientPeg = require("../../MatrixClientPeg"); var Notifier = require("../../Notifier"); @@ -85,6 +86,10 @@ module.exports = React.createClass({ }; }, + componentWillMount: function() { + this.favicon = new Favico({animation: 'none'}); + }, + componentDidMount: function() { this._autoRegisterAsGuest = false; if (this.props.enableGuest) { @@ -498,6 +503,7 @@ module.exports = React.createClass({ var cli = MatrixClientPeg.get(); var self = this; cli.on('sync', function(state, prevState) { + self.updateFavicon(); if (state === "SYNCING" && prevState === "SYNCING") { return; } @@ -756,6 +762,21 @@ module.exports = React.createClass({ this.showScreen("settings"); }, + updateFavicon: function() { + var notifCount = 0; + + var rooms = MatrixClientPeg.get().getRooms(); + for (var i = 0; i < rooms.length; ++i) { + if (rooms[i].hasMembershipState(MatrixClientPeg.get().credentials.userId, 'invite')) { + ++notifCount; + } else if (rooms[i].getUnreadNotificationCount()) { + notifCount += rooms[i].getUnreadNotificationCount(); + } + } + this.favicon.badge(notifCount); + document.title = (notifCount > 0 ? "["+notifCount+"] " : "")+"Vector"; + }, + onUserSettingsClose: function() { // XXX: use browser history instead to find the previous room? if (this.state.currentRoom) { diff --git a/src/components/views/rooms/RoomList.js b/src/components/views/rooms/RoomList.js index 9f9232e9dd..73b8d054e0 100644 --- a/src/components/views/rooms/RoomList.js +++ b/src/components/views/rooms/RoomList.js @@ -52,6 +52,7 @@ module.exports = React.createClass({ cli.on("Room.timeline", this.onRoomTimeline); cli.on("Room.name", this.onRoomName); cli.on("Room.tags", this.onRoomTags); + cli.on("Room.receipt", this.onRoomReceipt); cli.on("RoomState.events", this.onRoomStateEvents); cli.on("RoomMember.name", this.onRoomMemberName); @@ -93,6 +94,7 @@ module.exports = React.createClass({ if (MatrixClientPeg.get()) { MatrixClientPeg.get().removeListener("Room", this.onRoom); MatrixClientPeg.get().removeListener("Room.timeline", this.onRoomTimeline); + MatrixClientPeg.get().removeListener("Room.receipt", this.onRoomReceipt); MatrixClientPeg.get().removeListener("Room.name", this.onRoomName); MatrixClientPeg.get().removeListener("RoomState.events", this.onRoomStateEvents); } @@ -139,14 +141,6 @@ module.exports = React.createClass({ if (UnreadStatus.eventTriggersUnreadCount(ev)) { hl = 1; } - - var me = room.getMember(MatrixClientPeg.get().credentials.userId); - var actions = MatrixClientPeg.get().getPushActionsForEvent(ev); - if ((actions && actions.tweaks && actions.tweaks.highlight) || - (me && me.membership == "invite")) - { - hl = 2; - } } var newState = this.getRoomLists(); @@ -163,6 +157,19 @@ module.exports = React.createClass({ this.setState(newState); }, + onRoomReceipt: function(receiptEvent, room) { + // because if we read a notification, it will affect notification count + // only bother updating if there's a receipt from us + var receiptKeys = Object.keys(receiptEvent.getContent()); + for (var i = 0; i < receiptKeys.length; ++i) { + var rcpt = receiptEvent.getContent()[receiptKeys[i]]; + if (rcpt['m.read'] && rcpt['m.read'][MatrixClientPeg.get().credentials.userId]) { + this.refreshRoomList(); + break; + } + } + }, + onRoomName: function(room) { this._delayedRefreshRoomList(); },