diff --git a/src/ActiveRoomObserver.js b/src/ActiveRoomObserver.js
new file mode 100644
index 0000000000..d6fbb460b5
--- /dev/null
+++ b/src/ActiveRoomObserver.js
@@ -0,0 +1,77 @@
+/*
+Copyright 2017 New Vector Ltd
+
+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.
+*/
+
+import RoomViewStore from './stores/RoomViewStore';
+
+/**
+ * Consumes changes from the RoomViewStore and notifies specific things
+ * about when the active room changes. Unlike listening for RoomViewStore
+ * changes, you can subscribe to only changes relevant to a particular
+ * room.
+ *
+ * TODO: If we introduce an observer for something else, factor out
+ * the adding / removing of listeners & emitting into a common class.
+ */
+class ActiveRoomObserver {
+ constructor() {
+ this._listeners = {};
+
+ this._activeRoomId = RoomViewStore.getRoomId();
+ // TODO: We could self-destruct when the last listener goes away, or at least
+ // stop listening.
+ this._roomStoreToken = RoomViewStore.addListener(this._onRoomViewStoreUpdate.bind(this));
+ }
+
+ addListener(roomId, listener) {
+ if (!this._listeners[roomId]) this._listeners[roomId] = [];
+ this._listeners[roomId].push(listener);
+ }
+
+ removeListener(roomId, listener) {
+ if (this._listeners[roomId]) {
+ const i = this._listeners[roomId].indexOf(listener);
+ if (i > -1) {
+ this._listeners[roomId].splice(i, 1);
+ }
+ } else {
+ console.warn("Unregistering unrecognised listener (roomId=" + roomId + ")");
+ }
+ }
+
+ _emit(roomId) {
+ if (!this._listeners[roomId]) return;
+
+ for (const l of this._listeners[roomId]) {
+ l.call();
+ }
+ }
+
+ _onRoomViewStoreUpdate() {
+ // emit for the old room ID
+ if (this._activeRoomId) this._emit(this._activeRoomId);
+
+ // update our cache
+ this._activeRoomId = RoomViewStore.getRoomId();
+
+ // and emit for the new one
+ if (this._activeRoomId) this._emit(this._activeRoomId);
+ }
+}
+
+if (global.mx_ActiveRoomObserver === undefined) {
+ global.mx_ActiveRoomObserver = new ActiveRoomObserver();
+}
+export default global.mx_ActiveRoomObserver;
diff --git a/src/components/views/rooms/RoomList.js b/src/components/views/rooms/RoomList.js
index 27001ac954..b7b2e5ecea 100644
--- a/src/components/views/rooms/RoomList.js
+++ b/src/components/views/rooms/RoomList.js
@@ -63,7 +63,6 @@ module.exports = React.createClass({
propTypes: {
ConferenceHandler: React.PropTypes.any,
collapsed: React.PropTypes.bool.isRequired,
- currentRoom: React.PropTypes.string,
searchFilter: React.PropTypes.string,
},
diff --git a/src/components/views/rooms/RoomTile.js b/src/components/views/rooms/RoomTile.js
index 97568a52a1..a6065d8e92 100644
--- a/src/components/views/rooms/RoomTile.js
+++ b/src/components/views/rooms/RoomTile.js
@@ -1,5 +1,6 @@
/*
Copyright 2015, 2016 OpenMarket Ltd
+Copyright 2017 New Vector Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -27,6 +28,8 @@ var RoomNotifs = require('../../../RoomNotifs');
var FormattingUtils = require('../../../utils/FormattingUtils');
import AccessibleButton from '../elements/AccessibleButton';
var UserSettingsStore = require('../../../UserSettingsStore');
+import ActiveRoomObserver from '../../../ActiveRoomObserver';
+import RoomViewStore from '../../../stores/RoomViewStore';
module.exports = React.createClass({
displayName: 'RoomTile',
@@ -39,7 +42,6 @@ module.exports = React.createClass({
room: React.PropTypes.object.isRequired,
collapsed: React.PropTypes.bool.isRequired,
- selected: React.PropTypes.bool.isRequired,
unread: React.PropTypes.bool.isRequired,
highlight: React.PropTypes.bool.isRequired,
isInvite: React.PropTypes.bool.isRequired,
@@ -58,6 +60,7 @@ module.exports = React.createClass({
badgeHover : false,
menuDisplayed: false,
notifState: RoomNotifs.getRoomNotifsState(this.props.room.roomId),
+ selected: this.props.room.roomId === RoomViewStore.getRoomId(),
});
},
@@ -87,8 +90,15 @@ module.exports = React.createClass({
}
},
+ _onActiveRoomChange: function() {
+ this.setState({
+ selected: this.props.room.roomId === RoomViewStore.getRoomId(),
+ });
+ },
+
componentWillMount: function() {
MatrixClientPeg.get().on("accountData", this.onAccountData);
+ ActiveRoomObserver.addListener(this.props.room.roomId, this._onActiveRoomChange);
},
componentWillUnmount: function() {
@@ -96,6 +106,7 @@ module.exports = React.createClass({
if (cli) {
MatrixClientPeg.get().removeListener("accountData", this.onAccountData);
}
+ ActiveRoomObserver.removeListener(this.props.room.roomId, this._onActiveRoomChange);
},
onClick: function(ev) {
@@ -174,7 +185,7 @@ module.exports = React.createClass({
var classes = classNames({
'mx_RoomTile': true,
- 'mx_RoomTile_selected': this.props.selected,
+ 'mx_RoomTile_selected': this.state.selected,
'mx_RoomTile_unread': this.props.unread,
'mx_RoomTile_unreadNotify': notifBadges,
'mx_RoomTile_highlight': mentionBadges,
@@ -221,7 +232,7 @@ module.exports = React.createClass({
'mx_RoomTile_badgeShown': badges || this.state.badgeHover || this.state.menuDisplayed,
});
- if (this.props.selected) {
+ if (this.state.selected) {
let nameSelected =