123 lines
3.8 KiB
JavaScript
Executable File
123 lines
3.8 KiB
JavaScript
Executable File
/* @flow */
|
|
|
|
import React from 'react';
|
|
import PureRenderMixin from 'react-addons-pure-render-mixin';
|
|
import i18n from '../i18n';
|
|
import Flux from '../lib/flux';
|
|
import Avatar from './common/Avatar';
|
|
import ContextMenu from './common/ContextMenu';
|
|
import Scroller from './common/Scroller';
|
|
import UserPopout from './UserPopout';
|
|
import Popout from './common/Popout';
|
|
import UserContextMenu from './contextmenus/UserContextMenu';
|
|
import UserStore from '../stores/UserStore';
|
|
import PresenceStore from '../stores/PresenceStore';
|
|
import RelationshipStore from '../stores/RelationshipStore';
|
|
import TypingStore from '../stores/TypingStore';
|
|
import ChannelRecord from '../records/ChannelRecord';
|
|
import NicknameUtils from '../utils/NicknameUtils';
|
|
import {ContextMenuTypes} from '../Constants';
|
|
import {renderActivity, isStreaming} from '../utils/ActivityUtils';
|
|
import {getRecipients} from '../utils/PrivateChannelRecipientsUtils';
|
|
|
|
const PrivateChannelRecipient = React.createClass({
|
|
mixins: [Flux.LazyStoreListenerMixin(PresenceStore, RelationshipStore, TypingStore), PureRenderMixin],
|
|
|
|
getInitialState() {
|
|
return this.getStateFromStores();
|
|
},
|
|
|
|
getStateFromStores() {
|
|
const {user, channel} = this.props;
|
|
let status;
|
|
let activity;
|
|
if (RelationshipStore.isFriend(user.id) || user === UserStore.getCurrentUser()) {
|
|
status = PresenceStore.getStatus(user.id);
|
|
activity = PresenceStore.getActivity(user.id);
|
|
}
|
|
return {
|
|
typing: TypingStore.getTypingUsers(channel.id)[user.id] != null,
|
|
status,
|
|
activity,
|
|
};
|
|
},
|
|
|
|
handleContextMenu(e) {
|
|
const {user, channel} = this.props;
|
|
ContextMenu.openContextMenu(e, props =>
|
|
<UserContextMenu {...props} type={ContextMenuTypes.USER_GROUP_DM} user={user} channelId={channel.id} />
|
|
);
|
|
},
|
|
|
|
renderUserPopout(props) {
|
|
const {user, channel} = this.props;
|
|
return <UserPopout {...props} user={user} channelId={channel.id} />;
|
|
},
|
|
|
|
render() {
|
|
const {user, channel} = this.props;
|
|
const {status, typing} = this.state;
|
|
|
|
let activity;
|
|
if (this.state.activity) {
|
|
activity = <div className="member-activity">{renderActivity(this.state.activity)}</div>;
|
|
}
|
|
|
|
const username = NicknameUtils.getName(null, channel.id, user);
|
|
return (
|
|
<Popout closeOnScroll={false} render={this.renderUserPopout} position={Popout.LEFT} offsetX={15}>
|
|
<div onContextMenu={this.handleContextMenu} className="member">
|
|
<Avatar user={user} status={status} streaming={isStreaming(this.state.activity)} typing={typing} />
|
|
<div className="member-inner">
|
|
<div className="member-username">
|
|
<span className="member-username-inner">{username}</span>
|
|
</div>
|
|
{activity}
|
|
</div>
|
|
</div>
|
|
</Popout>
|
|
);
|
|
},
|
|
});
|
|
|
|
const PrivateChannelRecipients = React.createClass({
|
|
mixins: [Flux.LazyStoreListenerMixin(UserStore)],
|
|
|
|
propTypes: {
|
|
channel: React.PropTypes.instanceOf(ChannelRecord).isRequired,
|
|
},
|
|
|
|
getInitialState() {
|
|
return this.getStateFromStores();
|
|
},
|
|
|
|
getStateFromStores() {
|
|
return {
|
|
recipients: getRecipients(this.props.channel.recipients),
|
|
};
|
|
},
|
|
|
|
componentWillReceiveProps({channel}: {channel: ChannelRecord}) {
|
|
this.setState({recipients: getRecipients(channel.recipients)});
|
|
},
|
|
|
|
render() {
|
|
const {channel} = this.props;
|
|
const {recipients} = this.state;
|
|
return (
|
|
<div className="channel-members-wrap">
|
|
<Scroller className="channel-members" fade={true} theme="light">
|
|
<h2>{i18n.Messages.MEMBERS}—{recipients.length}</h2>
|
|
{recipients.map(props => <PrivateChannelRecipient {...props} channel={channel} />)}
|
|
</Scroller>
|
|
</div>
|
|
);
|
|
},
|
|
});
|
|
|
|
export default PrivateChannelRecipients;
|
|
|
|
|
|
|
|
// WEBPACK FOOTER //
|
|
// ./discord_app/components/PrivateChannelRecipients.js
|