Merge remote-tracking branch 'origin/develop' into dbkr/scalar
This commit is contained in:
commit
fdcebe1e56
21 changed files with 243 additions and 54 deletions
|
@ -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}
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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} />
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
},
|
||||
|
||||
|
|
|
@ -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":
|
||||
|
|
|
@ -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>
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue