Merge remote-tracking branch 'origin/develop' into dbkr/scalar

This commit is contained in:
David Baker 2016-06-06 17:19:38 +01:00
commit fdcebe1e56
21 changed files with 243 additions and 54 deletions

View file

@ -26,6 +26,7 @@ module.exports = React.createClass({
propTypes: {
roomId: React.PropTypes.string.isRequired,
onInvite: React.PropTypes.func.isRequired, // fn(inputText)
onThirdPartyInvite: React.PropTypes.func.isRequired, // fn(inputText)
onSearchQueryChanged: React.PropTypes.func // fn(inputText)
},
@ -49,10 +50,19 @@ module.exports = React.createClass({
}
},
componentDidMount: function() {
// initialise the email tile
this.onSearchQueryChanged('');
},
onInvite: function(ev) {
this.props.onInvite(this._input);
},
onThirdPartyInvite: function(ev) {
this.props.onThirdPartyInvite(this._input);
},
onSearchQueryChanged: function(input) {
this._input = input;
var EntityTile = sdk.getComponent("rooms.EntityTile");
@ -68,9 +78,10 @@ module.exports = React.createClass({
this._emailEntity = new Entities.newEntity(
<EntityTile key="dynamic_invite_tile" suppressOnHover={true} showInviteButton={true}
avatarJsx={ <BaseAvatar name="@" width={36} height={36} /> }
className="mx_EntityTile_invitePlaceholder"
presenceState="online" onClick={this.onInvite} name={label} />,
avatarJsx={ <BaseAvatar name="@" width={36} height={36} /> }
className="mx_EntityTile_invitePlaceholder"
presenceState="online" onClick={this.onThirdPartyInvite} name={"Invite by email"}
/>,
function(query) {
return true; // always show this
}
@ -89,7 +100,7 @@ module.exports = React.createClass({
}
return (
<SearchableEntityList searchPlaceholderText={"Invite/search by name, email, id"}
<SearchableEntityList searchPlaceholderText={"Search/invite by name, email, id"}
onSubmit={this.props.onInvite}
onQueryChanged={this.onSearchQueryChanged}
entities={entities}

View file

@ -340,6 +340,7 @@ module.exports = React.createClass({
},
type: 'm.room.guest_access',
state_key: '',
visibility: 'private',
}
],
}).then(
@ -367,7 +368,7 @@ module.exports = React.createClass({
action: 'leave_room',
room_id: this.props.member.roomId,
});
this.props.onFinished();
this.props.onFinished();
},
getInitialState: function() {

View file

@ -166,6 +166,25 @@ module.exports = React.createClass({
});
}, 500),
onThirdPartyInvite: function(inputText) {
var TextInputDialog = sdk.getComponent("dialogs.TextInputDialog");
Modal.createDialog(TextInputDialog, {
title: "Invite members by email",
description: "Please enter one or more email addresses",
value: inputText,
button: "Invite",
onFinished: (should_invite, addresses)=>{
if (should_invite) {
// defer the actual invite to the next event loop to give this
// Modal a chance to unmount in case onInvite() triggers a new one
setTimeout(()=>{
this.onInvite(addresses);
}, 0);
}
}
});
},
onInvite: function(inputText) {
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
var NeedToRegisterDialog = sdk.getComponent("dialogs.NeedToRegisterDialog");
@ -514,6 +533,7 @@ module.exports = React.createClass({
inviteMemberListSection = (
<InviteMemberList roomId={this.props.roomId}
onSearchQueryChanged={this.onSearchQueryChanged}
onThirdPartyInvite={this.onThirdPartyInvite}
onInvite={this.onInvite} />
);
}

View file

@ -46,6 +46,15 @@ module.exports = React.createClass({
},
onUploadClick: function(ev) {
if (MatrixClientPeg.get().isGuest()) {
var NeedToRegisterDialog = sdk.getComponent("dialogs.NeedToRegisterDialog");
Modal.createDialog(NeedToRegisterDialog, {
title: "Please Register",
description: "Guest users can't upload files. Please register to upload."
});
return;
}
this.refs.uploadInput.click();
},

View file

@ -36,7 +36,7 @@ module.exports = React.createClass({
getInitialState: function() {
var tags = {};
Object.keys(this.props.room.tags).forEach(function(tagName) {
tags[tagName] = {};
tags[tagName] = ['yep'];
});
var areNotifsMuted = false;
@ -186,7 +186,7 @@ module.exports = React.createClass({
// tags
if (this.state.tags_changed) {
var tagDiffs = ObjectUtils.getKeyValueArrayDiffs(originalState.tags, this.state.tags);
// [ {place: add, key: "m.favourite", val: "yep"} ]
// [ {place: add, key: "m.favourite", val: ["yep"]} ]
tagDiffs.forEach(function(diff) {
switch (diff.place) {
case "add":

View file

@ -48,6 +48,7 @@ var SearchableEntityList = React.createClass({
getInitialState: function() {
return {
query: "",
focused: false,
truncateAt: this.props.truncateAt,
results: this.getSearchResults("", this.props.entities)
};
@ -101,7 +102,7 @@ var SearchableEntityList = React.createClass({
getSearchResults: function(query, entities) {
if (!query || query.length === 0) {
return this.props.emptyQueryShowsAll ? entities : []
return this.props.emptyQueryShowsAll ? entities : [ entities[0] ]
}
return entities.filter(function(e) {
return e.matches(query);
@ -134,13 +135,27 @@ var SearchableEntityList = React.createClass({
<form onSubmit={this.onQuerySubmit} autoComplete="off">
<input className="mx_SearchableEntityList_query" id="mx_SearchableEntityList_query" type="text"
onChange={this.onQueryChanged} value={this.state.query}
onFocus={ ()=>{
if (this._blurTimeout) {
clearTimeout(this.blurTimeout);
}
this.setState({ focused: true });
} }
onBlur={ ()=>{
// nasty setTimeout heuristic to avoid the 'invite by email' prompt disappearing
// due to the onBlur before we can click on it
this._blurTimeout = setTimeout(
()=>{ this.setState({ focused: false }) },
300
);
} }
placeholder={this.props.searchPlaceholderText} />
</form>
);
}
var list;
if (this.state.results.length) {
if (this.state.results.length > 1 || this.state.focused) {
if (this.props.truncateAt) { // caller wants list truncated
var TruncatedList = sdk.getComponent("elements.TruncatedList");
list = (
@ -172,10 +187,10 @@ var SearchableEntityList = React.createClass({
}
return (
<div className={ "mx_SearchableEntityList " + (this.state.query.length ? "mx_SearchableEntityList_expanded" : "") }>
<div className={ "mx_SearchableEntityList " + (list ? "mx_SearchableEntityList_expanded" : "") }>
{ inputBox }
{ list }
{ this.state.query.length ? <div className="mx_SearchableEntityList_hrWrapper"><hr/></div> : '' }
{ list ? <div className="mx_SearchableEntityList_hrWrapper"><hr/></div> : '' }
</div>
);
}