diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index b70c89e2d8..9899f66cc5 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -64,6 +64,13 @@ module.exports = React.createClass({ getInitialState: function() { var s = { + // If we are viewing a room by alias, this contains the alias + currentRoomAlias: null, + + // The ID of the room we're viewing. This is either populated directly + // in the case where we view a room by ID or by RoomView when it resolves + // what ID an alias points at. + currentRoomId: null, logged_in: !!(MatrixClientPeg.get() && MatrixClientPeg.get().credentials), collapse_lhs: false, collapse_rhs: false, @@ -392,10 +399,10 @@ module.exports = React.createClass({ }); break; case 'view_room': - // Takes both room ID and room alias: if switching to a room the client is already - // know to be in (eg. user clicks on a room in the recents panel), supply only the - // ID. If the user is clicking on a room in the context of the alias being presented - // to them, supply the room alias and optionally the room ID. + // Takes either a room ID or room alias: if switching to a room the client is already + // known to be in (eg. user clicks on a room in the recents panel), supply the ID + // If the user is clicking on a room in the context of the alias being presented + // to them, supply the room alias. If both are supplied, the room ID will be ignored. this._viewRoom( payload.room_id, payload.room_alias, payload.show_settings, payload.event_id, payload.third_party_invite, payload.oob_data @@ -409,7 +416,7 @@ module.exports = React.createClass({ ); var roomIndex = -1; for (var i = 0; i < allRooms.length; ++i) { - if (allRooms[i].roomId == this.state.currentRoom) { + if (allRooms[i].roomId == this.state.currentRoomId) { roomIndex = i; break; } @@ -506,18 +513,11 @@ module.exports = React.createClass({ page_type: this.PageTypes.RoomView, thirdPartyInvite: thirdPartyInvite, roomOobData: oob_data, + currentRoomAlias: roomAlias, }; - // If an alias has been provided, we use that and only that, - // since otherwise we'll prefer to pass in an ID to RoomView - // but if we're not in the room, we should join by alias rather - // than ID. - if (roomAlias) { - newState.currentRoomAlias = roomAlias; - newState.currentRoom = null; - } else { - newState.currentRoomAlias = null; - newState.currentRoom = roomId; + if (!roomAlias) { + newState.currentRoomId = roomId; } // if we aren't given an explicit event id, look for one in the @@ -612,13 +612,13 @@ module.exports = React.createClass({ dis.dispatch(self.starting_room_alias_payload); delete self.starting_room_alias_payload; } else if (!self.state.page_type) { - if (!self.state.currentRoom) { + if (!self.state.currentRoomId) { var firstRoom = null; if (cli.getRooms() && cli.getRooms().length) { firstRoom = RoomListSorter.mostRecentActivityFirst( cli.getRooms() )[0].roomId; - self.setState({ready: true, currentRoom: firstRoom, page_type: self.PageTypes.RoomView}); + self.setState({ready: true, currentRoomId: firstRoom, page_type: self.PageTypes.RoomView}); } else { self.setState({ready: true, page_type: self.PageTypes.RoomDirectory}); } @@ -628,8 +628,8 @@ module.exports = React.createClass({ // we notifyNewScreen now because now the room will actually be displayed, // and (mostly) now we can get the correct alias. - var presentedId = self.state.currentRoom; - var room = MatrixClientPeg.get().getRoom(self.state.currentRoom); + var presentedId = self.state.currentRoomId; + var room = MatrixClientPeg.get().getRoom(self.state.currentRoomId); if (room) { var theAlias = MatrixTools.getCanonicalAliasForRoom(room); if (theAlias) presentedId = theAlias; @@ -979,10 +979,10 @@ module.exports = React.createClass({ onUserSettingsClose: function() { // XXX: use browser history instead to find the previous room? // or maintain a this.state.pageHistory in _setPage()? - if (this.state.currentRoom) { + if (this.state.currentRoomId) { dis.dispatch({ action: 'view_room', - room_id: this.state.currentRoom, + room_id: this.state.currentRoomId, }); } else { @@ -992,6 +992,13 @@ module.exports = React.createClass({ } }, + onRoomIdResolved: function(room_id) { + // It's the RoomView's resposibility to look up room aliases, but we need the + // ID to pass into things like the Member List, so the Room View tells us when + // its done that resolution so we can display things that take a room ID. + this.setState({currentRoomId: room_id}); + }, + render: function() { var LeftPanel = sdk.getComponent('structures.LeftPanel'); var RoomView = sdk.getComponent('structures.RoomView'); @@ -1022,17 +1029,18 @@ module.exports = React.createClass({ page_element = ( ); - right_panel = + right_panel = break; case this.PageTypes.UserSettings: page_element = @@ -1068,7 +1076,7 @@ module.exports = React.createClass({
{topBar}
- +
{page_element}
diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index 9fc335236c..e1b4c00175 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -55,9 +55,17 @@ module.exports = React.createClass({ propTypes: { ConferenceHandler: React.PropTypes.any, - // the ID for this room (or, if we don't know it, an alias for it) + // Either a room ID or room alias for the room to display. + // If the room is being displayed as a result of the user clicking + // on a room alias, the alias should be supplied. Otherwise, a room + // ID should be supplied. roomAddress: React.PropTypes.string.isRequired, + // If a room alias is passed to roomAddress, a function can be + // provided here that will be called with the ID of the room + // once it has been resolved. + onRoomIdResolved: React.PropTypes.func, + // An object representing a third party invite to join this room // Fields: // * inviteSignUrl (string) The URL used to join this room from an email invite @@ -94,24 +102,17 @@ module.exports = React.createClass({ }, getInitialState: function() { - var room; - if (this.props.roomAddress[0] == '!') { - room = MatrixClientPeg.get().getRoom(this.props.roomAddress); - } else { - room = MatrixTools.getRoomForAlias( - MatrixClientPeg.get().getRooms(), this.props.roomAddress - ); - } return { - room: room, - roomLoading: !room, + room: null, + roomId: null, + roomLoading: true, editingRoomSettings: false, uploadingRoomSettings: false, numUnreadMessages: 0, draggingFile: false, searching: false, searchResults: null, - hasUnsentMessages: this._hasUnsentMessages(room), + hasUnsentMessages: false, callState: null, guestsCanJoin: false, canPeek: false, @@ -143,6 +144,39 @@ module.exports = React.createClass({ } }); + if (this.props.roomAddress[0] == '#') { + // we always look up the alias from the directory server: + // we want the room that the given alias is pointing to + // right now. We may have joined that alias before but there's + // no guarantee the alias hasn't subsequently been remapped. + MatrixClientPeg.get().getRoomIdForAlias(this.props.roomAddress).done((result) => { + if (this.props.onRoomIdResolved) { + this.props.onRoomIdResolved(result.room_id); + } + var room = MatrixClientPeg.get().getRoom(result.room_id); + this.setState({ + room: room, + roomId: result.room_id, + roomLoading: !room, + hasUnsentMessages: this._hasUnsentMessages(room), + }, this._updatePeeking); + }, (err) => { + this.setState({ + roomLoading: false, + }); + }); + } else { + var room = MatrixClientPeg.get().getRoom(this.props.roomAddress); + this.setState({ + roomId: this.props.roomAddress, + room: room, + roomLoading: !room, + hasUnsentMessages: this._hasUnsentMessages(room), + }, this._updatePeeking); + } + }, + + _updatePeeking: function() { // if this is an unknown room then we're in one of three states: // - This is a room we can peek into (search engine) (we can /peek) // - This is a room we can publicly join or were invited to. (we can /join) @@ -150,10 +184,13 @@ module.exports = React.createClass({ // We can't try to /join because this may implicitly accept invites (!) // We can /peek though. If it fails then we present the join UI. If it // succeeds then great, show the preview (but we still may be able to /join!). - if (!this.state.room) { - console.log("Attempting to peek into room %s", this.props.roomAddress); + // Note that peeking works by room ID and room ID only, as opposed to joining + // which must be by alias or invite wherever possible (peeking currently does + // not work over federation). + if (!this.state.room && this.state.roomId) { + console.log("Attempting to peek into room %s", this.state.roomId); - MatrixClientPeg.get().peekInRoom(this.props.roomAddress).then((room) => { + MatrixClientPeg.get().peekInRoom(this.state.roomId).then((room) => { this.setState({ room: room, roomLoading: false, @@ -172,7 +209,7 @@ module.exports = React.createClass({ throw err; } }).done(); - } else { + } else if (this.state.room) { MatrixClientPeg.get().stopPeeking(); this._onRoomLoaded(this.state.room); }