mirror of https://github.com/vector-im/riot-web
Split out invite memberlist logic into its own component
parent
5dafe1f4a6
commit
3fa23798ea
|
@ -68,6 +68,7 @@ module.exports.components['views.room_settings.AliasSettings'] = require('./comp
|
|||
module.exports.components['views.room_settings.ColorSettings'] = require('./components/views/room_settings/ColorSettings');
|
||||
module.exports.components['views.rooms.EntityTile'] = require('./components/views/rooms/EntityTile');
|
||||
module.exports.components['views.rooms.EventTile'] = require('./components/views/rooms/EventTile');
|
||||
module.exports.components['views.rooms.InviteMemberList'] = require('./components/views/rooms/InviteMemberList');
|
||||
module.exports.components['views.rooms.MemberInfo'] = require('./components/views/rooms/MemberInfo');
|
||||
module.exports.components['views.rooms.MemberList'] = require('./components/views/rooms/MemberList');
|
||||
module.exports.components['views.rooms.MemberTile'] = require('./components/views/rooms/MemberTile');
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
Copyright 2015, 2016 OpenMarket Ltd
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
var React = require('react');
|
||||
var sdk = require("../../../index");
|
||||
var Entities = require("../../../Entities");
|
||||
var MatrixClientPeg = require("../../../MatrixClientPeg");
|
||||
|
||||
const INITIAL_SEARCH_RESULTS_COUNT = 10;
|
||||
|
||||
module.exports = React.createClass({
|
||||
displayName: 'InviteMemberList',
|
||||
|
||||
propTypes: {
|
||||
roomId: React.PropTypes.string.isRequired,
|
||||
onInvite: React.PropTypes.func.isRequired, // fn(inputText)
|
||||
onSearchQueryChanged: React.PropTypes.func // fn(inputText)
|
||||
},
|
||||
|
||||
getDefaultProps: function() {
|
||||
return {
|
||||
onSearchQueryChanged: function() {}
|
||||
};
|
||||
},
|
||||
|
||||
getInitialState: function() {
|
||||
return {};
|
||||
},
|
||||
|
||||
componentWillMount: function() {
|
||||
this._room = MatrixClientPeg.get().getRoom(this.props.roomId);
|
||||
this._emailEntity = null;
|
||||
// Load the complete user list for inviting new users
|
||||
// TODO: Keep this list bleeding-edge up-to-date. Practically speaking,
|
||||
// it will do for now not being updated as random new users join different
|
||||
// rooms as this list will be reloaded every room swap.
|
||||
this._userList = MatrixClientPeg.get().getUsers().filter((u) => {
|
||||
return !this._room.hasMembershipState(u.userId, "join");
|
||||
});
|
||||
console.log("%s users", this._userList.length);
|
||||
},
|
||||
|
||||
onSearchQueryChanged: function(input) {
|
||||
var EntityTile = sdk.getComponent("rooms.EntityTile");
|
||||
var BaseAvatar = sdk.getComponent("avatars.BaseAvatar");
|
||||
|
||||
var label = input;
|
||||
// if (input[0] === "@") {
|
||||
// label = input;
|
||||
// }
|
||||
// else {
|
||||
// label = "Email: " + input;
|
||||
// }
|
||||
|
||||
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.props.onInvite} name={label} />,
|
||||
function(query) {
|
||||
return true; // always show this
|
||||
}
|
||||
);
|
||||
|
||||
this.props.onSearchQueryChanged(input);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var SearchableEntityList = sdk.getComponent("rooms.SearchableEntityList");
|
||||
var entities = Entities.fromUsers(this._userList || [], true, this.props.onInvite);
|
||||
|
||||
// Add an "Email: foo@bar.com" tile as the first tile
|
||||
if (this._emailEntity) {
|
||||
entities.unshift(this._emailEntity);
|
||||
}
|
||||
|
||||
return (
|
||||
<SearchableEntityList searchPlaceholderText={"Invite / Search"}
|
||||
onSubmit={this.props.onInvite}
|
||||
onQueryChanged={this.onSearchQueryChanged}
|
||||
entities={entities}
|
||||
truncateAt={INITIAL_SEARCH_RESULTS_COUNT}/>
|
||||
);
|
||||
}
|
||||
});
|
|
@ -24,7 +24,6 @@ var sdk = require('../../../index');
|
|||
var GeminiScrollbar = require('react-gemini-scrollbar');
|
||||
var rate_limited_func = require('../../../ratelimitedfunc');
|
||||
|
||||
var INITIAL_SEARCH_RESULTS_COUNT = 10;
|
||||
var INITIAL_LOAD_NUM_MEMBERS = 30;
|
||||
var SHARE_HISTORY_WARNING = "Newly invited users will see the history of this room. "+
|
||||
"If you'd prefer invited users not to see messages that were sent before they joined, "+
|
||||
|
@ -78,12 +77,9 @@ module.exports = React.createClass({
|
|||
setTimeout(function() {
|
||||
if (!self.isMounted()) return;
|
||||
// lazy load to prevent it blocking the first render
|
||||
self._loadUserList();
|
||||
|
||||
self.setState({
|
||||
members: self.roomMembers()
|
||||
});
|
||||
|
||||
}, 50);
|
||||
|
||||
// Attach a SINGLE listener for global presence changes then locate the
|
||||
|
@ -105,24 +101,6 @@ module.exports = React.createClass({
|
|||
MatrixClientPeg.get().on("User.presence", updateUserState);
|
||||
this.userPresenceFn = updateUserState;
|
||||
},
|
||||
// Remember to set 'key' on a MemberList to the ID of the room it's for
|
||||
/*componentWillReceiveProps: function(newProps) {
|
||||
},*/
|
||||
|
||||
_loadUserList: function() {
|
||||
var room = MatrixClientPeg.get().getRoom(this.props.roomId);
|
||||
if (!room) {
|
||||
return; // we'll do it later
|
||||
}
|
||||
|
||||
// Load the complete user list for inviting new users
|
||||
// TODO: Keep this list bleeding-edge up-to-date. Practically speaking,
|
||||
// it will do for now not being updated as random new users join different
|
||||
// rooms as this list will be reloaded every room swap.
|
||||
this.userList = MatrixClientPeg.get().getUsers().filter(function(u) {
|
||||
return !room.hasMembershipState(u.userId, "join");
|
||||
});
|
||||
},
|
||||
|
||||
onRoom: function(room) {
|
||||
if (room.roomId !== this.props.roomId) {
|
||||
|
@ -132,7 +110,6 @@ module.exports = React.createClass({
|
|||
// we need to wait till the room is fully populated with state
|
||||
// before refreshing the member list else we get a stale list.
|
||||
this._updateList();
|
||||
this._loadUserList();
|
||||
},
|
||||
|
||||
onRoomStateMember: function(ev, state, member) {
|
||||
|
@ -335,27 +312,6 @@ module.exports = React.createClass({
|
|||
},
|
||||
|
||||
onSearchQueryChanged: function(input) {
|
||||
var EntityTile = sdk.getComponent("rooms.EntityTile");
|
||||
var BaseAvatar = sdk.getComponent("avatars.BaseAvatar");
|
||||
|
||||
var label = input;
|
||||
// if (input[0] === "@") {
|
||||
// label = input;
|
||||
// }
|
||||
// else {
|
||||
// label = "Email: " + input;
|
||||
// }
|
||||
|
||||
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.bind(this, input)} name={label} />,
|
||||
function(query) {
|
||||
return true; // always show this
|
||||
}
|
||||
);
|
||||
|
||||
this.setState({
|
||||
searchQuery: input
|
||||
});
|
||||
|
@ -406,32 +362,9 @@ module.exports = React.createClass({
|
|||
return memberList;
|
||||
},
|
||||
|
||||
inviteTile: function() {
|
||||
if (this.state.inviting) {
|
||||
var Loader = sdk.getComponent("elements.Spinner");
|
||||
return (
|
||||
<Loader />
|
||||
);
|
||||
} else {
|
||||
var SearchableEntityList = sdk.getComponent("rooms.SearchableEntityList");
|
||||
var entities = Entities.fromUsers(this.userList || [], true, this.onInvite);
|
||||
|
||||
// Add an "Email: foo@bar.com" tile as the first tile
|
||||
if (this._emailEntity) {
|
||||
entities.unshift(this._emailEntity);
|
||||
}
|
||||
|
||||
return (
|
||||
<SearchableEntityList searchPlaceholderText={"Invite / Search"}
|
||||
onSubmit={this.onInvite}
|
||||
onQueryChanged={this.onSearchQueryChanged}
|
||||
entities={entities}
|
||||
truncateAt={INITIAL_SEARCH_RESULTS_COUNT}/>
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var InviteMemberList = sdk.getComponent("rooms.InviteMemberList");
|
||||
|
||||
var invitedSection = null;
|
||||
var invitedMemberTiles = this.makeMemberTiles('invite', this.state.searchQuery);
|
||||
if (invitedMemberTiles.length > 0) {
|
||||
|
@ -444,10 +377,27 @@ module.exports = React.createClass({
|
|||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
var inviteMemberListSection;
|
||||
if (this.state.inviting) {
|
||||
var Loader = sdk.getComponent("elements.Spinner");
|
||||
inviteMemberListSection = (
|
||||
<Loader />
|
||||
);
|
||||
}
|
||||
else {
|
||||
inviteMemberListSection = (
|
||||
<InviteMemberList roomId={this.props.roomId}
|
||||
onSearchQueryChanged={this.onSearchQueryChanged}
|
||||
onInvite={this.onInvite} />
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
var TruncatedList = sdk.getComponent("elements.TruncatedList");
|
||||
return (
|
||||
<div className="mx_MemberList">
|
||||
{this.inviteTile()}
|
||||
{inviteMemberListSection}
|
||||
<GeminiScrollbar autoshow={true} className="mx_MemberList_joined mx_MemberList_outerWrapper">
|
||||
<TruncatedList className="mx_MemberList_wrapper" truncateAt={this.state.truncateAt}
|
||||
createOverflowElement={this._createOverflowTile}>
|
||||
|
|
Loading…
Reference in New Issue