Fix /join to be consistent with the other code

Plus a number of other tidyups:

 * Fix /join to dispatch a view_room for the room alias
   with the additional auto_join parameter
 * Make RoomView automatically join the room if the auto_join
   parameter is true and the user isn't already in it
 * Tidy up RoomView's peeking code, also fixing
   https://github.com/vector-im/vector-web/issues/1220
   in react-sdk (although it still requires a synapse change
   to actually fix, but react-sdk does 'the right thing').
 * Remove duplication of usage text from /join command
 * Amalgamate MatrixChat::_viewRoom's many, many parameters
   into an object and sort out case consistency a little.
This commit is contained in:
David Baker 2016-06-20 16:30:51 +01:00
parent 8103a795ec
commit d8dedae084
3 changed files with 73 additions and 79 deletions

View file

@ -132,46 +132,25 @@ var commands = {
}), }),
// Join a room // Join a room
join: new Command("join", "<room_alias>", function(room_id, args) { join: new Command("join", "#alias:domain", function(room_id, args) {
if (args) { if (args) {
var matches = args.match(/^(\S+)$/); var matches = args.match(/^(\S+)$/);
if (matches) { if (matches) {
var room_alias = matches[1]; var room_alias = matches[1];
if (room_alias[0] !== '#') { if (room_alias[0] !== '#') {
return reject("Usage: /join #alias:domain"); return reject(this.getUsage());
} }
if (!room_alias.match(/:/)) { if (!room_alias.match(/:/)) {
room_alias += ':' + MatrixClientPeg.get().getDomain(); room_alias += ':' + MatrixClientPeg.get().getDomain();
} }
// Try to find a room with this alias dis.dispatch({
// XXX: do we need to do this? Doesn't the JS SDK suppress duplicate attempts to join the same room? action: 'view_room',
var foundRoom = MatrixTools.getRoomForAlias( room_alias: room_alias,
MatrixClientPeg.get().getRooms(), auto_join: true,
room_alias });
);
if (foundRoom) { // we've already joined this room, view it if it's not archived. return success();
var me = foundRoom.getMember(MatrixClientPeg.get().credentials.userId);
if (me && me.membership !== "leave") {
dis.dispatch({
action: 'view_room',
room_id: foundRoom.roomId
});
return success();
}
}
// otherwise attempt to join this alias.
return success(
MatrixClientPeg.get().joinRoom(room_alias).then(
function(room) {
dis.dispatch({
action: 'view_room',
room_id: room.roomId
});
})
);
} }
} }
return reject(this.getUsage()); return reject(this.getUsage());

View file

@ -403,10 +403,7 @@ module.exports = React.createClass({
// known to be in (eg. user clicks on a room in the recents panel), supply the ID // 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 // 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. // to them, supply the room alias. If both are supplied, the room ID will be ignored.
this._viewRoom( this._viewRoom(payload);
payload.room_id, payload.room_alias, payload.show_settings, payload.event_id,
payload.third_party_invite, payload.oob_data
);
break; break;
case 'view_prev_room': case 'view_prev_room':
roomIndexDelta = -1; roomIndexDelta = -1;
@ -423,7 +420,7 @@ module.exports = React.createClass({
} }
roomIndex = (roomIndex + roomIndexDelta) % allRooms.length; roomIndex = (roomIndex + roomIndexDelta) % allRooms.length;
if (roomIndex < 0) roomIndex = allRooms.length - 1; if (roomIndex < 0) roomIndex = allRooms.length - 1;
this._viewRoom(allRooms[roomIndex].roomId); this._viewRoom({ room_id: allRooms[roomIndex].room_id });
break; break;
case 'view_indexed_room': case 'view_indexed_room':
var allRooms = RoomListSorter.mostRecentActivityFirst( var allRooms = RoomListSorter.mostRecentActivityFirst(
@ -431,7 +428,7 @@ module.exports = React.createClass({
); );
var roomIndex = payload.roomIndex; var roomIndex = payload.roomIndex;
if (allRooms[roomIndex]) { if (allRooms[roomIndex]) {
this._viewRoom(allRooms[roomIndex].roomId); this._viewRoom({ room_id: allRooms[roomIndex].roomId });
} }
break; break;
case 'view_user_settings': case 'view_user_settings':
@ -491,39 +488,45 @@ module.exports = React.createClass({
// switch view to the given room // switch view to the given room
// //
// eventId is optional and will cause a switch to the context of that // @param {Object} room_info Object containing data about the room to be joined
// particular event. // @param {string} room_info.room_id ID of the room to join. One of room_id or room_alias must be given.
// @param {Object} thirdPartyInvite Object containing data about the third party // @param {string} room_info.room_alias Alias of the room to join. One of room_id or room_alias must be given.
// @param {boolean} room_info.auto_join If true, automatically attempt to join the room if not already a member.
// @param {string} room_info.show_settings ??
// @param {string} room_info.event_id ID of the event in this room to show: this will cause a switch to the
// context of that particular event. Optional.
// @param {Object} room_info.third_party_invite Object containing data about the third party
// we received to join the room, if any. // we received to join the room, if any.
// @param {string} thirdPartyInvite.inviteSignUrl 3pid invite sign URL // @param {string} room_info.third_party_invite.inviteSignUrl 3pid invite sign URL
// @param {string} thirdPartyInvite.invitedwithEmail The email address the invite was sent to // @param {string} room_info.third_party_invite.invitedwithEmail The email address the invite was sent to
// @param {Object} oob_data Object of additional data about the room // @param {Object} room_info.oob_data Object of additional data about the room
// that has been passed out-of-band (eg. // that has been passed out-of-band (eg.
// room name and avatar from an invite email) // room name and avatar from an invite email)
_viewRoom: function(roomId, roomAlias, showSettings, eventId, thirdPartyInvite, oob_data) { _viewRoom: function(room_info) {
// before we switch room, record the scroll state of the current room // before we switch room, record the scroll state of the current room
this._updateScrollMap(); this._updateScrollMap();
this.focusComposer = true; this.focusComposer = true;
var newState = { var newState = {
initialEventId: eventId, initialEventId: room_info.event_id,
highlightedEventId: eventId, highlightedEventId: room_info.event_id,
initialEventPixelOffset: undefined, initialEventPixelOffset: undefined,
page_type: this.PageTypes.RoomView, page_type: this.PageTypes.RoomView,
thirdPartyInvite: thirdPartyInvite, thirdPartyInvite: room_info.third_party_invite,
roomOobData: oob_data, roomOobData: room_info.oob_data,
currentRoomAlias: roomAlias, currentRoomAlias: room_info.room_alias,
autoJoin: room_info.auto_join,
}; };
if (!roomAlias) { if (!room_info.room_alias) {
newState.currentRoomId = roomId; newState.currentRoomId = room_info.room_id;
} }
// if we aren't given an explicit event id, look for one in the // if we aren't given an explicit event id, look for one in the
// scrollStateMap. // scrollStateMap.
if (!eventId) { if (!room_info.event_id) {
var scrollState = this.scrollStateMap[roomId]; var scrollState = this.scrollStateMap[room_info.room_id];
if (scrollState) { if (scrollState) {
newState.initialEventId = scrollState.focussedEvent; newState.initialEventId = scrollState.focussedEvent;
newState.initialEventPixelOffset = scrollState.pixelOffset; newState.initialEventPixelOffset = scrollState.pixelOffset;
@ -536,8 +539,8 @@ module.exports = React.createClass({
// the new screen yet (we won't be showing it yet) // the new screen yet (we won't be showing it yet)
// The normal case where this happens is navigating // The normal case where this happens is navigating
// to the room in the URL bar on page load. // to the room in the URL bar on page load.
var presentedId = roomAlias || roomId; var presentedId = room_info.room_alias || room_info.room_id;
var room = MatrixClientPeg.get().getRoom(roomId); var room = MatrixClientPeg.get().getRoom(room_info.room_id);
if (room) { if (room) {
var theAlias = MatrixTools.getDisplayAliasForRoom(room); var theAlias = MatrixTools.getDisplayAliasForRoom(room);
if (theAlias) presentedId = theAlias; if (theAlias) presentedId = theAlias;
@ -553,15 +556,15 @@ module.exports = React.createClass({
// Tinter.tint(color_scheme.primary_color, color_scheme.secondary_color); // Tinter.tint(color_scheme.primary_color, color_scheme.secondary_color);
} }
if (eventId) { if (room_info.event_id) {
presentedId += "/"+eventId; presentedId += "/"+event_id;
} }
this.notifyNewScreen('room/'+presentedId); this.notifyNewScreen('room/'+presentedId);
newState.ready = true; newState.ready = true;
} }
this.setState(newState); this.setState(newState);
if (this.refs.roomView && showSettings) { if (this.refs.roomView && room_info.showSettings) {
this.refs.roomView.showSettings(true); this.refs.roomView.showSettings(true);
} }
}, },
@ -1030,6 +1033,7 @@ module.exports = React.createClass({
<RoomView <RoomView
ref="roomView" ref="roomView"
roomAddress={this.state.currentRoomAlias || this.state.currentRoomId} roomAddress={this.state.currentRoomAlias || this.state.currentRoomId}
autoJoin={this.state.autoJoin}
onRoomIdResolved={this.onRoomIdResolved} onRoomIdResolved={this.onRoomIdResolved}
eventId={this.state.initialEventId} eventId={this.state.initialEventId}
thirdPartyInvite={this.state.thirdPartyInvite} thirdPartyInvite={this.state.thirdPartyInvite}

View file

@ -159,7 +159,7 @@ module.exports = React.createClass({
roomId: result.room_id, roomId: result.room_id,
roomLoading: !room, roomLoading: !room,
hasUnsentMessages: this._hasUnsentMessages(room), hasUnsentMessages: this._hasUnsentMessages(room),
}, this._updatePeeking); }, this._onHaveRoom);
}, (err) => { }, (err) => {
this.setState({ this.setState({
roomLoading: false, roomLoading: false,
@ -172,11 +172,11 @@ module.exports = React.createClass({
room: room, room: room,
roomLoading: !room, roomLoading: !room,
hasUnsentMessages: this._hasUnsentMessages(room), hasUnsentMessages: this._hasUnsentMessages(room),
}, this._updatePeeking); }, this._onHaveRoom);
} }
}, },
_updatePeeking: function() { _onHaveRoom: function() {
// if this is an unknown room then we're in one of three states: // 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 peek into (search engine) (we can /peek)
// - This is a room we can publicly join or were invited to. (we can /join) // - This is a room we can publicly join or were invited to. (we can /join)
@ -187,29 +187,40 @@ module.exports = React.createClass({
// Note that peeking works by room ID and room ID only, as opposed to joining // 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 // which must be by alias or invite wherever possible (peeking currently does
// not work over federation). // 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.state.roomId).then((room) => { // NB. We peek if we are not in the room, although if we try to peek into
this.setState({ // a room in which we have a member event (ie. we've left) synapse will just
room: room, // send us the same data as we get in the sync (ie. the last events we saw).
roomLoading: false, var my_member = this.state.room ? this.state.room.getMember(MatrixClientPeg.get().credentials.userId) : null;
}); var user_is_in_room = my_member ? my_member.membership == 'join' : false;
this._onRoomLoaded(room);
}, (err) => { if (!user_is_in_room && this.state.roomId) {
// This won't necessarily be a MatrixError, but we duck-type if (this.props.autoJoin) {
// here and say if it's got an 'errcode' key with the right value, this.onJoinButtonClicked();
// it means we can't peek. } else if (this.state.roomId) {
if (err.errcode == "M_GUEST_ACCESS_FORBIDDEN") { console.log("Attempting to peek into room %s", this.state.roomId);
// This is fine: the room just isn't peekable (we assume).
MatrixClientPeg.get().peekInRoom(this.state.roomId).then((room) => {
this.setState({ this.setState({
room: room,
roomLoading: false, roomLoading: false,
}); });
} else { this._onRoomLoaded(room);
throw err; }, (err) => {
} // This won't necessarily be a MatrixError, but we duck-type
}).done(); // here and say if it's got an 'errcode' key with the right value,
} else if (this.state.room) { // it means we can't peek.
if (err.errcode == "M_GUEST_ACCESS_FORBIDDEN") {
// This is fine: the room just isn't peekable (we assume).
this.setState({
roomLoading: false,
});
} else {
throw err;
}
}).done();
}
} else if (user_is_in_room) {
MatrixClientPeg.get().stopPeeking(); MatrixClientPeg.get().stopPeeking();
this._onRoomLoaded(this.state.room); this._onRoomLoaded(this.state.room);
} }
@ -992,7 +1003,7 @@ module.exports = React.createClass({
this.setState({ this.setState({
rejecting: true rejecting: true
}); });
MatrixClientPeg.get().leave(this.props.roomAddress).done(function() { MatrixClientPeg.get().leave(this.props.roomId).done(function() {
dis.dispatch({ action: 'view_next_room' }); dis.dispatch({ action: 'view_next_room' });
self.setState({ self.setState({
rejecting: false rejecting: false