Pass room metadata from 3pid invite emails all the way through to the relevant components so we can display it.

This commit is contained in:
David Baker 2016-03-01 18:23:57 +00:00
parent db1e1c7df0
commit 9085a2a866
4 changed files with 102 additions and 38 deletions

View file

@ -312,7 +312,10 @@ module.exports = React.createClass({
}); });
break; break;
case 'view_room': case 'view_room':
this._viewRoom(payload.room_id, payload.show_settings, payload.event_id, payload.invite_sign_url); this._viewRoom(
payload.room_id, payload.show_settings, payload.event_id,
payload.invite_sign_url, payload.oob_data
);
break; break;
case 'view_prev_room': case 'view_prev_room':
roomIndexDelta = -1; roomIndexDelta = -1;
@ -350,6 +353,7 @@ module.exports = React.createClass({
room_id: foundRoom.roomId, room_id: foundRoom.roomId,
event_id: payload.event_id, event_id: payload.event_id,
invite_sign_url: payload.invite_sign_url, invite_sign_url: payload.invite_sign_url,
oob_data: payload.oob_data,
}); });
return; return;
} }
@ -361,6 +365,7 @@ module.exports = React.createClass({
room_id: result.room_id, room_id: result.room_id,
event_id: payload.event_id, event_id: payload.event_id,
invite_sign_url: payload.invite_sign_url, invite_sign_url: payload.invite_sign_url,
room_oob_data: payload.room_oob_data,
}); });
}); });
break; break;
@ -448,7 +453,10 @@ module.exports = React.createClass({
// //
// eventId is optional and will cause a switch to the context of that // eventId is optional and will cause a switch to the context of that
// particular event. // particular event.
_viewRoom: function(roomId, showSettings, eventId, invite_sign_url) { // @param {Object} room_oob_data Object of additional data about the room
// that has been passed out-of-band (eg.
// room name and avatar from an invite email)
_viewRoom: function(roomId, showSettings, eventId, invite_sign_url, oob_data) {
// 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();
@ -461,6 +469,7 @@ module.exports = React.createClass({
initialEventPixelOffset: undefined, initialEventPixelOffset: undefined,
page_type: this.PageTypes.RoomView, page_type: this.PageTypes.RoomView,
inviteSignUrl: invite_sign_url, inviteSignUrl: invite_sign_url,
roomOobData: oob_data,
}; };
// 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
@ -552,10 +561,12 @@ module.exports = React.createClass({
room_alias: self.starting_room_alias, room_alias: self.starting_room_alias,
event_id: self.starting_event_id, event_id: self.starting_event_id,
invite_sign_url: self.starting_room_invite_sign_url, invite_sign_url: self.starting_room_invite_sign_url,
room_oob_data: self.starting_room_oob_data,
}); });
delete self.starting_room_alias; delete self.starting_room_alias;
delete self.starting_event_id; delete self.starting_event_id;
delete self.starting_room_invite_sign_url; delete self.starting_room_invite_sign_url;
delete self.starting_room_oob_data;
} else if (!self.state.page_type) { } else if (!self.state.page_type) {
if (!self.state.currentRoom) { if (!self.state.currentRoom) {
var firstRoom = null; var firstRoom = null;
@ -675,6 +686,13 @@ module.exports = React.createClass({
var segments = screen.substring(5).split('/'); var segments = screen.substring(5).split('/');
var roomString = segments[0]; var roomString = segments[0];
var eventId = segments[1]; // undefined if no event id given var eventId = segments[1]; // undefined if no event id given
var oob_data = {
name: params.room_name,
avatarUrl: params.room_avatar_url,
inviterName: params.inviter_name,
};
if (roomString[0] == '#') { if (roomString[0] == '#') {
if (this.state.logged_in) { if (this.state.logged_in) {
dis.dispatch({ dis.dispatch({
@ -682,11 +700,16 @@ module.exports = React.createClass({
room_alias: roomString, room_alias: roomString,
event_id: eventId, event_id: eventId,
invite_sign_url: params.signurl, invite_sign_url: params.signurl,
oob_data: oob_data,
}); });
} else { } else {
// Okay, we'll take you here soon... // Okay, we'll take you here soon...
// XXX: There are way too many of these:
// It would probably be better to handle whether the SDK is
// ready or not in the view_room_alias handler instead.
this.starting_room_alias = roomString; this.starting_room_alias = roomString;
this.starting_room_invite_sign_url = params.signurl; this.starting_room_invite_sign_url = params.signurl;
this.starting_room_oob_data = oob_data;
this.starting_event_id = eventId; this.starting_event_id = eventId;
// ...but you're still going to have to log in. // ...but you're still going to have to log in.
this.notifyNewScreen('login'); this.notifyNewScreen('login');
@ -697,6 +720,7 @@ module.exports = React.createClass({
room_id: roomString, room_id: roomString,
event_id: eventId, event_id: eventId,
invite_sign_url: params.signurl, invite_sign_url: params.signurl,
oob_data: oob_data,
}); });
} }
} }
@ -884,6 +908,7 @@ module.exports = React.createClass({
roomId={this.state.currentRoom} roomId={this.state.currentRoom}
eventId={this.state.initialEventId} eventId={this.state.initialEventId}
inviteSignUrl={this.state.inviteSignUrl} inviteSignUrl={this.state.inviteSignUrl}
oobData={this.state.roomOobData}
highlightedEventId={this.state.highlightedEventId} highlightedEventId={this.state.highlightedEventId}
eventPixelOffset={this.state.initialEventPixelOffset} eventPixelOffset={this.state.initialEventPixelOffset}
key={this.state.currentRoom} key={this.state.currentRoom}

View file

@ -59,6 +59,12 @@ module.exports = React.createClass({
// (given as part of the link in the invite email) // (given as part of the link in the invite email)
inviteSignUrl: React.PropTypes.string, inviteSignUrl: React.PropTypes.string,
// Any data about the room that would normally come from the Home Server
// but has been passed out-of-band, eg. the room name and avatar URL
// from an email invite (a workaround for the fact that we can't
// get this information from the HS using an email invite).
oobData: React.PropTypes.object,
// id of an event to jump to. If not given, will go to the end of the // id of an event to jump to. If not given, will go to the end of the
// live timeline. // live timeline.
eventId: React.PropTypes.string, eventId: React.PropTypes.string,
@ -1052,13 +1058,19 @@ module.exports = React.createClass({
); );
} }
else { else {
var inviterName = undefined;
if (this.props.oobData) {
inviterName = this.props.oobData.inviterName;
}
return ( return (
<div className="mx_RoomView"> <div className="mx_RoomView">
<RoomHeader ref="header" room={this.state.room} simpleHeader="Join room"/> <RoomHeader ref="header" room={this.state.room} oobData={this.props.oobData} />
<div className="mx_RoomView_auxPanel"> <div className="mx_RoomView_auxPanel">
<RoomPreviewBar onJoinClick={ this.onJoinButtonClicked } <RoomPreviewBar onJoinClick={ this.onJoinButtonClicked }
canJoin={ true } canPreview={ false } canJoin={ true } canPreview={ false }
spinner={this.state.joining} spinner={this.state.joining}
inviterName={inviterName}
/> />
</div> </div>
<div className="mx_RoomView_messagePanel"></div> <div className="mx_RoomView_messagePanel"></div>
@ -1293,6 +1305,7 @@ module.exports = React.createClass({
return ( return (
<div className={ "mx_RoomView" + (inCall ? " mx_RoomView_inCall" : "") } ref="roomView"> <div className={ "mx_RoomView" + (inCall ? " mx_RoomView_inCall" : "") } ref="roomView">
<RoomHeader ref="header" room={this.state.room} searchInfo={searchInfo} <RoomHeader ref="header" room={this.state.room} searchInfo={searchInfo}
oobData={this.state.oobData}
editing={this.state.editingRoomSettings} editing={this.state.editingRoomSettings}
onSearchClick={this.onSearchClick} onSearchClick={this.onSearchClick}
onSettingsClick={this.onSettingsClick} onSettingsClick={this.onSettingsClick}

View file

@ -14,6 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
var React = require('react'); var React = require('react');
var ContentRepo = require("matrix-js-sdk").ContentRepo;
var MatrixClientPeg = require('../../../MatrixClientPeg'); var MatrixClientPeg = require('../../../MatrixClientPeg');
var Avatar = require('../../../Avatar'); var Avatar = require('../../../Avatar');
var sdk = require("../../../index"); var sdk = require("../../../index");
@ -22,7 +23,8 @@ module.exports = React.createClass({
displayName: 'RoomAvatar', displayName: 'RoomAvatar',
propTypes: { propTypes: {
room: React.PropTypes.object.isRequired, room: React.PropTypes.object,
oobData: React.PropTypes.object,
width: React.PropTypes.number, width: React.PropTypes.number,
height: React.PropTypes.number, height: React.PropTypes.number,
resizeMethod: React.PropTypes.string resizeMethod: React.PropTypes.string
@ -32,7 +34,8 @@ module.exports = React.createClass({
return { return {
width: 36, width: 36,
height: 36, height: 36,
resizeMethod: 'crop' resizeMethod: 'crop',
oobData: {},
} }
}, },
@ -50,7 +53,12 @@ module.exports = React.createClass({
getImageUrls: function(props) { getImageUrls: function(props) {
return [ return [
this.getRoomAvatarUrl(props), // highest priority ContentRepo.getHttpUriForMxc(
MatrixClientPeg.get().getHomeserverUrl(),
props.oobData.avatarUrl,
props.width, props.height, props.resizeMethod
), // highest priority
this.getRoomAvatarUrl(props),
this.getOneToOneAvatar(props), this.getOneToOneAvatar(props),
this.getFallbackAvatar(props) // lowest priority this.getFallbackAvatar(props) // lowest priority
].filter(function(url) { ].filter(function(url) {
@ -59,6 +67,8 @@ module.exports = React.createClass({
}, },
getRoomAvatarUrl: function(props) { getRoomAvatarUrl: function(props) {
if (!this.props.room) return null;
return props.room.getAvatarUrl( return props.room.getAvatarUrl(
MatrixClientPeg.get().getHomeserverUrl(), MatrixClientPeg.get().getHomeserverUrl(),
props.width, props.height, props.resizeMethod, props.width, props.height, props.resizeMethod,
@ -67,6 +77,8 @@ module.exports = React.createClass({
}, },
getOneToOneAvatar: function(props) { getOneToOneAvatar: function(props) {
if (!this.props.room) return null;
var mlist = props.room.currentState.members; var mlist = props.room.currentState.members;
var userIds = []; var userIds = [];
// for .. in optimisation to return early if there are >2 keys // for .. in optimisation to return early if there are >2 keys
@ -103,14 +115,20 @@ module.exports = React.createClass({
}, },
getFallbackAvatar: function(props) { getFallbackAvatar: function(props) {
if (!this.props.room) return null;
return Avatar.defaultAvatarUrlForString(props.room.roomId); return Avatar.defaultAvatarUrlForString(props.room.roomId);
}, },
render: function() { render: function() {
var BaseAvatar = sdk.getComponent("avatars.BaseAvatar"); var BaseAvatar = sdk.getComponent("avatars.BaseAvatar");
var roomName = this.props.room ? this.props.room.name : this.props.oobData.name;
return ( return (
<BaseAvatar {...this.props} name={this.props.room.name} <BaseAvatar {...this.props} name={roomName}
idName={this.props.room.roomId} urls={this.state.urls} /> idName={this.props.room ? this.props.room.roomId : null}
urls={this.state.urls} />
); );
} }
}); });

View file

@ -33,6 +33,7 @@ module.exports = React.createClass({
propTypes: { propTypes: {
room: React.PropTypes.object, room: React.PropTypes.object,
oobData: React.PropTypes.object,
editing: React.PropTypes.bool, editing: React.PropTypes.bool,
onSettingsClick: React.PropTypes.func, onSettingsClick: React.PropTypes.func,
onSaveClick: React.PropTypes.func, onSaveClick: React.PropTypes.func,
@ -217,18 +218,27 @@ module.exports = React.createClass({
} }
// XXX: this is a bit inefficient - we could just compare room.name for 'Empty room'... // XXX: this is a bit inefficient - we could just compare room.name for 'Empty room'...
var members = this.props.room.getJoinedMembers();
var settingsHint = false; var settingsHint = false;
if (members.length === 1 && members[0].userId === MatrixClientPeg.get().credentials.userId) { var members = this.props.room ? this.props.room.getJoinedMembers() : undefined;
var name = this.props.room.currentState.getStateEvents('m.room.name', ''); if (members) {
if (!name || !name.getContent().name) { if (members.length === 1 && members[0].userId === MatrixClientPeg.get().credentials.userId) {
settingsHint = true; var name = this.props.room.currentState.getStateEvents('m.room.name', '');
if (!name || !name.getContent().name) {
settingsHint = true;
}
} }
} }
var roomName;
if (this.props.oobData && this.props.oobData.name) {
roomName = this.props.oobData.name;
} else {
this.props.room.name;
}
name = name =
<div className="mx_RoomHeader_name" onClick={this.props.onSettingsClick}> <div className="mx_RoomHeader_name" onClick={this.props.onSettingsClick}>
<div className={ "mx_RoomHeader_nametext " + (settingsHint ? "mx_RoomHeader_settingsHint" : "") } title={ this.props.room.name }>{ this.props.room.name }</div> <div className={ "mx_RoomHeader_nametext " + (settingsHint ? "mx_RoomHeader_settingsHint" : "") } title={ roomName }>{ roomName }</div>
{ searchStatus } { searchStatus }
<div className="mx_RoomHeader_settingsButton" title="Settings"> <div className="mx_RoomHeader_settingsButton" title="Settings">
<TintableSvg src="img/settings.svg" width="12" height="12"/> <TintableSvg src="img/settings.svg" width="12" height="12"/>
@ -246,36 +256,34 @@ module.exports = React.createClass({
onValueChanged={ this.onTopicChanged } onValueChanged={ this.onTopicChanged }
initialValue={ this.state.topic }/> initialValue={ this.state.topic }/>
} else { } else {
var topic = this.props.room.currentState.getStateEvents('m.room.topic', ''); var topic = this.props.room ? this.props.room.currentState.getStateEvents('m.room.topic', '') : '';
if (topic) topic_el = <div className="mx_RoomHeader_topic" ref="topic" title={ topic.getContent().topic }>{ topic.getContent().topic }</div>; if (topic) topic_el = <div className="mx_RoomHeader_topic" ref="topic" title={ topic.getContent().topic }>{ topic.getContent().topic }</div>;
} }
var roomAvatar = null; var roomAvatar = null;
if (this.props.room) { if (can_set_room_avatar) {
if (can_set_room_avatar) { roomAvatar = (
roomAvatar = ( <div className="mx_RoomHeader_avatarPicker">
<div className="mx_RoomHeader_avatarPicker"> <div onClick={ this.onAvatarPickerClick }>
<div onClick={ this.onAvatarPickerClick }> <ChangeAvatar ref="changeAvatar" room={this.props.room} showUploadSection={false} width={48} height={48} />
<ChangeAvatar ref="changeAvatar" room={this.props.room} showUploadSection={false} width={48} height={48} />
</div>
<div className="mx_RoomHeader_avatarPicker_edit">
<label htmlFor="avatarInput" ref="file_label">
<img src="img/camera.svg"
alt="Upload avatar" title="Upload avatar"
width="17" height="15" />
</label>
<input id="avatarInput" type="file" onChange={ this.onAvatarSelected }/>
</div>
</div> </div>
); <div className="mx_RoomHeader_avatarPicker_edit">
} <label htmlFor="avatarInput" ref="file_label">
else { <img src="img/camera.svg"
roomAvatar = ( alt="Upload avatar" title="Upload avatar"
<div onClick={this.props.onSettingsClick}> width="17" height="15" />
<RoomAvatar room={this.props.room} width={48} height={48}/> </label>
<input id="avatarInput" type="file" onChange={ this.onAvatarSelected }/>
</div> </div>
); </div>
} );
}
else {
roomAvatar = (
<div onClick={this.props.onSettingsClick}>
<RoomAvatar room={this.props.room} width={48} height={48} oobData={this.props.oobData} />
</div>
);
} }
var leave_button; var leave_button;