2017-06-08_509bba0/509bba0_unpacked_with_node_modules/discord_app/components/UserPopout.js
2022-07-26 10:06:20 -07:00

198 lines
5.9 KiB
JavaScript
Executable file

/* @flow */
import React, {PropTypes} from 'react';
import PureRenderMixin from 'react-addons-pure-render-mixin';
import classNames from 'classnames';
import Flux from '../lib/flux';
import i18n from '../i18n';
import lodash from 'lodash';
import DiscordTag from './common/DiscordTag';
import Avatar from './common/Avatar';
import Protip from './common/Protip';
import Note from './common/Note';
import QuickMessage from './common/QuickMessage';
import MemberRolesList from './MemberRolesList';
import {renderActivity, isStreaming, getStreamURL} from '../utils/ActivityUtils';
import PresenceStore from '../stores/PresenceStore';
import UserSettingsStore from '../stores/UserSettingsStore';
import UserStore from '../stores/UserStore';
import GuildMemberStore from '../stores/GuildMemberStore';
import GuildStore from '../stores/GuildStore';
import UserProfileModalActionCreators from '../actions/UserProfileModalActionCreators';
import NicknameUtils from '../utils/NicknameUtils';
import type GuildRecord from '../records/GuildRecord';
import type {Activity} from '../utils/ActivityUtils';
import '../styles/user_popout.styl';
type GuildMember = ?{
userId: string,
nick: ?string,
roles: Array<string>,
colorString: ?string,
hoistRoleId: ?string,
};
const BodySection = ({name, label, body}) =>
<div className={`section ${name}`}>
<div className="label">
<span className={`icon icon-${name}`} />
{label}
</div>
{body}
</div>;
BodySection.propTypes = {
name: PropTypes.string.isRequired,
label: PropTypes.string.isRequired,
body: PropTypes.any,
};
const UserPopout = React.createClass({
mixins: [Flux.LazyStoreListenerMixin(GuildMemberStore), PureRenderMixin],
propTypes: {
guildId: PropTypes.string,
channelId: PropTypes.string,
user: PropTypes.object.isRequired,
popoutKey: PropTypes.string,
setNote: PropTypes.bool,
onClose: PropTypes.func,
},
getDefaultProps() {
return {
setNote: false,
};
},
getInitialState() {
return this.getStateFromStores();
},
getStateFromStores(): {
me: boolean,
guild: ?GuildRecord,
activity: ?Activity,
userRoles: Array<string>,
guildMember: GuildMember,
status: ?string,
nickname: string,
} {
const {guildId, user, channelId} = this.props;
const currentUser = UserStore.getCurrentUser();
const me = currentUser === user;
const guildMember = guildId != null ? GuildMemberStore.getMember(guildId, user.id) : null;
const userRoles = guildMember ? guildMember.roles : [];
const nickname = NicknameUtils.getNickname(guildId, channelId, user);
return {
me,
guild: guildId != null ? GuildStore.getGuild(guildId) : null,
activity: PresenceStore.getActivity(user.id),
status: user.isNonUserBot() ? null : PresenceStore.getStatus(user.id),
userRoles,
guildMember,
nickname,
};
},
close() {
const {onClose} = this.props;
onClose && onClose();
},
handleViewProfile() {
UserProfileModalActionCreators.open(this.props.user.id);
this.close();
},
render() {
const {me, guild, activity, status, userRoles, guildMember, nickname} = this.state;
// eslint-disable-next-line no-unused-vars
const {user, popoutKey, setNote, onClose, guildId, channelId, ...props} = this.props;
const isNonUserBot = user.isNonUserBot();
const numRoles = userRoles.length;
// Check against all mutual Guilds to see if your DM permissions allow you to send a message
let canDM = false;
if (!me) {
lodash(GuildMemberStore.memberOf(user.id))
.map(guildId => UserSettingsStore.isGuildRestricted(guildId))
.forEach(isRestricted => {
if (!isRestricted) {
canDM = true;
}
});
}
let roles = null;
if (!!guildMember) {
roles = (
<BodySection
name="roles"
label={i18n.Messages.ROLES_LIST.format({numRoles})}
body={<MemberRolesList guild={guild} user={user} userRoles={userRoles} popoutKey={popoutKey} />}
/>
);
}
const streaming = isStreaming(activity);
let liveOnTwitch;
if (streaming) {
liveOnTwitch = (
<a className="live-on-twitch" href={getStreamURL(activity)} target="_blank" rel="noreferrer">
<span className="live" />
{i18n.Messages.LIVE_ON_TWITCH}
</a>
);
}
return (
<div className="user-popout" {...props}>
<header className={classNames('header', {streaming})}>
<div
className={classNames('avatar-wrapper', {'no-hover': isNonUserBot})}
onClick={!isNonUserBot && this.handleViewProfile}>
<div className="avatar-hint">View Profile</div>
<Avatar user={user} size="popout" status={status} animate />
</div>
<div className={classNames('username-wrapper', {'has-nickname': nickname && nickname.length})}>
{nickname && <div className="nickname">{nickname}</div>}
<DiscordTag user={user} invertBotColor={true} hideDiscriminator={isNonUserBot} />
{activity && <div className="activity">{renderActivity(activity)}</div>}
{liveOnTwitch}
</div>
</header>
{!isNonUserBot &&
<div className="body">
{roles}
<BodySection name="notes" label={i18n.Messages.NOTE} body={<Note userId={user.id} autoFocus={setNote} />} />
</div>}
{!isNonUserBot &&
<div className="footer">
{canDM &&
<div className="quick-message-wrapper">
<QuickMessage user={user} autoFocus={!setNote} onClose={onClose} />
</div>}
<div className="update-notice">
<Protip type="inline" tip={i18n.Messages.CONTEXT_MENU_HINT} />
</div>
</div>}
</div>
);
},
});
export default UserPopout;
// WEBPACK FOOTER //
// ./discord_app/components/UserPopout.js