/* @flow */
import React from 'react';
import Flux from '../../lib/flux';
import i18n from '../../i18n';
import lodash from 'lodash';
import classNames from 'classnames';
import fuzzysearch from 'fuzzysearch';
import GuildSettingsStore from '../../stores/GuildSettingsStore';
import GuildMemberStore from '../../stores/GuildMemberStore';
import UserSettingsStore from '../../stores/UserSettingsStore';
import UserStore from '../../stores/UserStore';
import PermissionStore from '../../stores/PermissionStore';
import StreamerModeStore from '../../stores/StreamerModeStore';
import PopoutActionCreators from '../../actions/PopoutActionCreators';
import GuildSettingsActionCreators from '../../actions/GuildSettingsActionCreators';
import PruneGuildModalActionCreators from '../../actions/PruneGuildModalActionCreators';
import {LazyContentScroller} from '../common/StandardSidebarView';
import ContextMenu from '../common/ContextMenu';
import UserContextMenu from '../contextmenus/UserContextMenu';
import RoleList from '../common/RoleList';
import SearchableQuickSelect from '../common/SearchableQuickSelect';
import Tooltip from '../common/Tooltip';
import IconButton from '../../uikit/IconButton';
import OverflowMenuIcon from '../../uikit/icons/OverflowMenuIcon';
import BotTag from '../../uikit/BotTag';
import Avatar from '../../uikit/Avatar';
import Flex from '../../uikit/Flex';
import {FormTitle, FormTitleTags, FormText, FormTextTypes, FormDivider, FormSection} from '../../uikit/form';
import SearchBar from '../../uikit/SearchBar';
import {ContextMenuTypes, Permissions, ThemeTypes} from '../../Constants';
import './GuildSettingsMembers.styl';
import '../../styles/shared/hover_card.styl';
const ROLE_FILTER_POPOUT_ID = 'quick-roles--select';
class Member extends React.PureComponent {
_isMounted = false;
state: {
overflowShown: boolean,
};
constructor(props) {
super(props);
this.state = {
overflowShown: false,
};
(this: any).showOverflow = this.showOverflow.bind(this);
(this: any).handleOverflowClose = this.handleOverflowClose.bind(this);
}
componentDidMount() {
this._isMounted = true;
}
componentWillUnmount() {
this._isMounted = false;
}
showOverflow(e: Event) {
const {guild, user} = this.props;
this.setState({overflowShown: true});
ContextMenu.openContextMenu(
e,
props =>
,
{
onClose: this.handleOverflowClose,
}
);
}
renderOwnerHelpIcon() {
const {user, theme, guild} = this.props;
if (user.id !== guild.ownerId) {
return null;
}
const iconSrc = theme === ThemeTypes.DARK
? require('../../images/ic_crown_dark_24px.svg')
: require('../../images/ic_crown_light_24px.svg');
return (
);
}
render() {
const {user, member, streamerMode, guild} = this.props;
const {overflowShown} = this.state;
const style = {
color: member.colorString,
};
return (
{member.nick || user.toString()}
{user.bot ? : null}
{this.renderOwnerHelpIcon()}
{streamerMode ? null : @{user.tag}}
);
}
handleOverflowClose() {
if (this._isMounted) {
this.setState({overflowShown: false});
}
}
}
class GuildSettingsMembers extends React.PureComponent {
state: {
roleFilterQuery: string,
};
constructor(props) {
super(props);
this.state = {
roleFilterQuery: '',
};
(this: any).renderHeader = this.renderHeader.bind(this);
(this: any).renderPruneAction = this.renderPruneAction.bind(this);
(this: any).handleQueryChange = this.handleQueryChange.bind(this);
(this: any).handleQueryClear = this.handleQueryClear.bind(this);
(this: any).handlePruneClick = this.handlePruneClick.bind(this);
(this: any).handleRoleFilterQueryChange = this.handleRoleFilterQueryChange.bind(this);
(this: any).handleRoleFilterQueryClear = this.handleRoleFilterQueryClear.bind(this);
}
componentDidUpdate(prevProps, prevState) {
if (this.state.roleFilterQuery !== prevState.roleFilterQuery) {
PopoutActionCreators.rerender(ROLE_FILTER_POPOUT_ID);
}
}
handlePruneClick() {
PruneGuildModalActionCreators.open(this.props.guild.id);
}
renderPruneAction() {
const {canPrune} = this.props;
if (!canPrune) {
return null;
}
return (
{' — '}
{i18n.Messages.PRUNE}
);
}
renderHeader(filteredMembers) {
const {roleFilterQuery} = this.state;
const {guild, searchQuery, selectedRoleId} = this.props;
const value = {};
const items = lodash(guild.roles)
.sortBy(role => -role.position)
.filter(role => {
if (role.id === selectedRoleId) {
value.label = role.name;
}
return fuzzysearch(roleFilterQuery.toLowerCase(), role.name.toLowerCase());
})
.map(role => ({
value: role.id,
color: role.colorString,
children: role.name,
selected: role.id === selectedRoleId,
}))
.value();
const searchProps = {
query: roleFilterQuery,
onChange: this.handleRoleFilterQueryChange,
onClear: this.handleRoleFilterQueryClear,
placeholder: i18n.Messages.SEARCH_ROLES,
};
return (
{i18n.Messages.GUILD_SETTINGS_MEMBERS_SERVER_MEMBERS}
{i18n.Messages.MEMBERS_HEADER.format({members: filteredMembers.length})}
{this.renderPruneAction()}
);
}
makeSearchFilter() {
let {searchQuery} = this.props;
if (searchQuery == null || searchQuery.length === 0) {
return () => true;
} else {
return ({user, member}) => {
searchQuery = searchQuery.toLowerCase();
const username = user.username.toLowerCase();
const nick = member.nick != null ? member.nick.toLowerCase() : null;
return fuzzysearch(searchQuery, username) || (nick != null && fuzzysearch(searchQuery, nick));
};
}
}
makeRoleFilter() {
const {guild, selectedRoleId} = this.props;
return ({member}) => selectedRoleId === guild.id || member.roles.indexOf(selectedRoleId) !== -1;
}
renderMembers(filteredMembers) {
const {guild, currentUser, streamerMode, theme} = this.props;
return lodash(filteredMembers)
.sortBy(({comparator}) => comparator)
.map(({member, user}) =>
)
.value();
}
render() {
const {members} = this.props;
const filteredMembers = lodash(members)
.map(member => {
const user = UserStore.getUser(member.userId);
return {
member,
user,
comparator: (user != null ? member.nick || user.username : '').toLowerCase(),
};
})
.filter(this.makeSearchFilter())
.filter(this.makeRoleFilter())
.value();
return (
{this.renderMembers(filteredMembers)}
);
}
handleQueryChange(query) {
GuildSettingsActionCreators.setSearchQuery(query);
}
handleQueryClear() {
GuildSettingsActionCreators.setSearchQuery('');
}
handleRoleChange({value}) {
GuildSettingsActionCreators.selectRole(value);
}
handleRoleFilterQueryChange(roleFilterQuery) {
this.setState({roleFilterQuery});
}
handleRoleFilterQueryClear() {
this.setState({
roleFilterQuery: '',
});
}
}
const GuildSettingsMembersWrapped = Flux.connectStores(
[GuildSettingsStore, UserSettingsStore, GuildMemberStore, StreamerModeStore],
() => {
const {guild, searchQuery, selectedRoleId} = GuildSettingsStore.getProps();
return {
guild,
selectedRoleId,
searchQuery: searchQuery || '',
members: GuildMemberStore.getMembers(guild.id),
theme: UserSettingsStore.theme,
currentUser: UserStore.getCurrentUser(),
canPrune: PermissionStore.can(Permissions.KICK_MEMBERS, guild),
streamerMode: StreamerModeStore.enabled,
};
}
)(GuildSettingsMembers);
export default GuildSettingsMembersWrapped;
// WEBPACK FOOTER //
// ./discord_app/components/guild_settings/GuildSettingsMembers.js