diff --git a/src/components/views/rooms/PinnedEventsPanel.js b/src/components/views/rooms/PinnedEventsPanel.js index deea03f030..5a99d9ab2d 100644 --- a/src/components/views/rooms/PinnedEventsPanel.js +++ b/src/components/views/rooms/PinnedEventsPanel.js @@ -71,6 +71,25 @@ module.exports = React.createClass({ this.setState({ loading: false, pinned }); }); } + + this._updateReadState(); + }, + + _updateReadState: function() { + const pinnedEvents = this.props.room.currentState.getStateEvents("m.room.pinned_events", ""); + if (!pinnedEvents) return; // nothing to read + + let lastReadEvent = null; + const readPinsEvent = this.props.room.getAccountData("im.vector.room.read_pins"); + if (readPinsEvent) { + lastReadEvent = readPinsEvent.getContent().last_read_id; + } + + if (lastReadEvent !== pinnedEvents.getId()) { + MatrixClientPeg.get().setRoomAccountData(this.props.room.roomId, "im.vector.room.read_pins", { + last_read_id: pinnedEvents.getId(), + }); + } }, _getPinnedTiles: function() { diff --git a/src/components/views/rooms/RoomHeader.js b/src/components/views/rooms/RoomHeader.js index 4df0ff738c..ea5748db60 100644 --- a/src/components/views/rooms/RoomHeader.js +++ b/src/components/views/rooms/RoomHeader.js @@ -65,6 +65,7 @@ module.exports = React.createClass({ componentDidMount: function() { const cli = MatrixClientPeg.get(); cli.on("RoomState.events", this._onRoomStateEvents); + cli.on("Room.accountData", this._onRoomAccountData); // When a room name occurs, RoomState.events is fired *before* // room.name is updated. So we have to listen to Room.name as well as @@ -87,6 +88,7 @@ module.exports = React.createClass({ const cli = MatrixClientPeg.get(); if (cli) { cli.removeListener("RoomState.events", this._onRoomStateEvents); + cli.removeListener("Room.accountData", this._onRoomAccountData); } }, @@ -99,6 +101,13 @@ module.exports = React.createClass({ this._rateLimitedUpdate(); }, + _onRoomAccountData: function(event, room) { + if (!this.props.room || room.roomId !== this.props.room.roomId) return; + if (event.getType() !== "im.vector.room.read_pins") return; + + this._rateLimitedUpdate(); + }, + _rateLimitedUpdate: new RateLimitedFunc(function() { /* eslint-disable babel/no-invalid-this */ this.forceUpdate(); @@ -139,6 +148,25 @@ module.exports = React.createClass({ dis.dispatch({ action: 'show_right_panel' }); }, + _hasUnreadPins: function() { + const currentPinEvent = this.props.room.currentState.getStateEvents("m.room.pinned_events", ''); + if (!currentPinEvent) return false; + if (currentPinEvent.getContent().pinned && currentPinEvent.getContent().pinned.length <= 0) { + return false; // no pins == nothing to read + } + + const readPinsEvent = this.props.room.getAccountData("im.vector.room.read_pins"); + if (readPinsEvent) { + const lastReadEvent = readPinsEvent.getContent().last_read_id; + if (lastReadEvent) { + return currentPinEvent.getId() !== lastReadEvent; + } + } + + // There's pins, and we haven't read any of them + return true; + }, + /** * After editing the settings, get the new name for the room * @@ -302,8 +330,14 @@ module.exports = React.createClass({ } if (this.props.onPinnedClick && UserSettingsStore.isFeatureEnabled('feature_pinning')) { + let newPinsNotification = null; + if (this._hasUnreadPins()) { + newPinsNotification = (
); + } pinnedEventsButton = - + + { newPinsNotification } ; }