mirror of
https://github.com/element-hq/element-web
synced 2024-11-28 12:28:50 +03:00
Split out invite memberlist logic into its own component
This commit is contained in:
parent
5dafe1f4a6
commit
3fa23798ea
3 changed files with 118 additions and 70 deletions
|
@ -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.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.EntityTile'] = require('./components/views/rooms/EntityTile');
|
||||||
module.exports.components['views.rooms.EventTile'] = require('./components/views/rooms/EventTile');
|
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.MemberInfo'] = require('./components/views/rooms/MemberInfo');
|
||||||
module.exports.components['views.rooms.MemberList'] = require('./components/views/rooms/MemberList');
|
module.exports.components['views.rooms.MemberList'] = require('./components/views/rooms/MemberList');
|
||||||
module.exports.components['views.rooms.MemberTile'] = require('./components/views/rooms/MemberTile');
|
module.exports.components['views.rooms.MemberTile'] = require('./components/views/rooms/MemberTile');
|
||||||
|
|
97
src/components/views/rooms/InviteMemberList.js
Normal file
97
src/components/views/rooms/InviteMemberList.js
Normal file
|
@ -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 GeminiScrollbar = require('react-gemini-scrollbar');
|
||||||
var rate_limited_func = require('../../../ratelimitedfunc');
|
var rate_limited_func = require('../../../ratelimitedfunc');
|
||||||
|
|
||||||
var INITIAL_SEARCH_RESULTS_COUNT = 10;
|
|
||||||
var INITIAL_LOAD_NUM_MEMBERS = 30;
|
var INITIAL_LOAD_NUM_MEMBERS = 30;
|
||||||
var SHARE_HISTORY_WARNING = "Newly invited users will see the history of this room. "+
|
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, "+
|
"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() {
|
setTimeout(function() {
|
||||||
if (!self.isMounted()) return;
|
if (!self.isMounted()) return;
|
||||||
// lazy load to prevent it blocking the first render
|
// lazy load to prevent it blocking the first render
|
||||||
self._loadUserList();
|
|
||||||
|
|
||||||
self.setState({
|
self.setState({
|
||||||
members: self.roomMembers()
|
members: self.roomMembers()
|
||||||
});
|
});
|
||||||
|
|
||||||
}, 50);
|
}, 50);
|
||||||
|
|
||||||
// Attach a SINGLE listener for global presence changes then locate the
|
// 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);
|
MatrixClientPeg.get().on("User.presence", updateUserState);
|
||||||
this.userPresenceFn = 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) {
|
onRoom: function(room) {
|
||||||
if (room.roomId !== this.props.roomId) {
|
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
|
// we need to wait till the room is fully populated with state
|
||||||
// before refreshing the member list else we get a stale list.
|
// before refreshing the member list else we get a stale list.
|
||||||
this._updateList();
|
this._updateList();
|
||||||
this._loadUserList();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
onRoomStateMember: function(ev, state, member) {
|
onRoomStateMember: function(ev, state, member) {
|
||||||
|
@ -335,27 +312,6 @@ module.exports = React.createClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
onSearchQueryChanged: function(input) {
|
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({
|
this.setState({
|
||||||
searchQuery: input
|
searchQuery: input
|
||||||
});
|
});
|
||||||
|
@ -406,32 +362,9 @@ module.exports = React.createClass({
|
||||||
return memberList;
|
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() {
|
render: function() {
|
||||||
|
var InviteMemberList = sdk.getComponent("rooms.InviteMemberList");
|
||||||
|
|
||||||
var invitedSection = null;
|
var invitedSection = null;
|
||||||
var invitedMemberTiles = this.makeMemberTiles('invite', this.state.searchQuery);
|
var invitedMemberTiles = this.makeMemberTiles('invite', this.state.searchQuery);
|
||||||
if (invitedMemberTiles.length > 0) {
|
if (invitedMemberTiles.length > 0) {
|
||||||
|
@ -444,10 +377,27 @@ module.exports = React.createClass({
|
||||||
</div>
|
</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");
|
var TruncatedList = sdk.getComponent("elements.TruncatedList");
|
||||||
return (
|
return (
|
||||||
<div className="mx_MemberList">
|
<div className="mx_MemberList">
|
||||||
{this.inviteTile()}
|
{inviteMemberListSection}
|
||||||
<GeminiScrollbar autoshow={true} className="mx_MemberList_joined mx_MemberList_outerWrapper">
|
<GeminiScrollbar autoshow={true} className="mx_MemberList_joined mx_MemberList_outerWrapper">
|
||||||
<TruncatedList className="mx_MemberList_wrapper" truncateAt={this.state.truncateAt}
|
<TruncatedList className="mx_MemberList_wrapper" truncateAt={this.state.truncateAt}
|
||||||
createOverflowElement={this._createOverflowTile}>
|
createOverflowElement={this._createOverflowTile}>
|
||||||
|
|
Loading…
Reference in a new issue