import {
IdentityStore,
FeatureUsageStore,
React,
PropTypes,
DOMUtils,
RegExpUtils,
Utils,
} from 'mailspring-exports';
import { RetinaImg } from 'mailspring-component-kit';
import moment from 'moment-timezone';
import ParticipantProfileDataSource from './participant-profile-data-source';
class ProfilePictureOrColorBox extends React.Component {
static propTypes = {
loading: PropTypes.bool,
contact: PropTypes.object,
profilePicture: PropTypes.string,
};
render() {
const { contact, loading, avatar } = this.props;
const hue = Utils.hueForString(contact.email);
const bgColor = `hsl(${hue}, 50%, 45%)`;
let content = (
{contact.nameAbbreviation()}
);
if (loading) {
content = (
);
}
if (avatar) {
content = ;
}
return (
);
}
}
class SocialProfileLink extends React.Component {
static propTypes = {
service: PropTypes.string,
handle: PropTypes.string,
};
render() {
const { handle, service } = this.props;
if (!handle) {
return false;
}
return (
);
}
}
class TextBlockWithAutolinkedElements extends React.Component {
static propTypes = {
className: PropTypes.string,
text: PropTypes.string,
};
render() {
if (!this.props.text) {
return false;
}
const nodes = [];
const hashtagOrMentionRegex = RegExpUtils.hashtagOrMentionRegex();
let remainder = this.props.text;
let match = null;
let count = 0;
/* I thought we were friends. */
/* eslint no-cond-assign: 0 */
while ((match = hashtagOrMentionRegex.exec(remainder))) {
// the first char of the match is whitespace, match[1] is # or @, match[2] is the tag itself.
nodes.push(remainder.substr(0, match.index + 1));
if (match[1] === '#') {
nodes.push(
{`#${match[2]}`}
);
}
if (match[1] === '@') {
nodes.push({`@${match[2]}`});
}
remainder = remainder.substr(match.index + match[0].length);
count += 1;
}
nodes.push(remainder);
return {nodes}
;
}
}
class IconRow extends React.Component {
static propTypes = {
node: PropTypes.node,
icon: PropTypes.string,
};
render() {
const { node, icon } = this.props;
if (!node) {
return false;
}
return (
{node}
);
}
}
class LocationRow extends React.Component {
static propTypes = {
location: PropTypes.string,
};
render() {
return (
{this.props.location}
{' ['}
View
{']'}
)
}
/>
);
}
}
export default class SidebarParticipantProfile extends React.Component {
static displayName = 'SidebarParticipantProfile';
static propTypes = {
contact: PropTypes.object,
contactThreads: PropTypes.array,
};
static containerStyles = {
order: 0,
};
constructor(props) {
super(props);
this.state = {
loaded: false,
loading: false,
trialing: !IdentityStore.hasProFeatures(),
};
const contactState = ParticipantProfileDataSource.getCache(props.contact.email);
if (contactState) {
this.state = Object.assign(this.state, { loaded: true }, contactState);
}
}
componentDidMount() {
this._mounted = true;
if (!this.state.loaded && !this.state.trialing) {
// Wait until we know they've "settled" on this email to reduce the number of
// requests to the contact search endpoint.
this.setState({ loading: true });
setTimeout(this._onFindContact, 2000);
}
}
componentWillUnmount() {
this._mounted = false;
}
_onClickedToTry = async () => {
try {
await FeatureUsageStore.markUsedOrUpgrade('contact-profiles', {
usedUpHeader: 'All Contact Previews Used',
usagePhrase: 'view contact profiles for',
iconUrl: 'mailspring://participant-profile/assets/ic-contact-profile-modal@2x.png',
});
} catch (err) {
// user does not have access to this feature
return;
}
this._onFindContact();
};
_onFindContact = async () => {
if (!this._mounted) {
return;
}
if (!this.state.loading) {
this.setState({ loading: true });
}
ParticipantProfileDataSource.find(this.props.contact.email).then(result => {
if (!this._mounted) {
return;
}
this.setState(Object.assign({ loading: false, loaded: true }, result));
});
};
_onSelect = event => {
const el = event.target;
const sel = document.getSelection();
if (el.contains(sel.anchorNode) && !sel.isCollapsed) {
return;
}
const anchor = DOMUtils.findFirstTextNode(el);
const focus = DOMUtils.findLastTextNode(el);
if (anchor && focus && focus.data) {
sel.setBaseAndExtent(anchor, 0, focus, focus.data.length);
}
};
_renderFindCTA() {
if (!this.state.trialing || this.state.loaded) {
return;
}
if (!this.props.contact.email || Utils.likelyNonHumanEmail(this.props.contact.email)) {
return;
}
return (
The contact sidebar in Mailspring Pro shows information about the people and companies
you're emailing with.
{!this.state.loading ? `Try it Now` : `Loading...`}
);
}
_renderCompanyInfo() {
const {
name,
domain,
category,
description,
location,
timeZone,
logo,
facebook,
twitter,
linkedin,
crunchbase,
type,
ticker,
phone,
metrics,
} =
this.state.company || {};
if (!name) {
return;
}
let employees = null;
let funding = null;
if (metrics) {
if (metrics.raised) {
funding = `Raised $${(metrics.raised / 1 || 0).toLocaleString()}`;
} else if (metrics.marketCap) {
funding = `Market cap $${(metrics.marketCap / 1 || 0).toLocaleString()}`;
}
if (metrics.employees) {
employees = `${(metrics.employees / 1 || 0).toLocaleString()} employees`;
} else if (metrics.employeesRange) {
employees = `${metrics.employeesRange} employees`;
}
}
return (
{logo && (
)}
{name}
{domain && (
{domain}
)}
{`${timeZone.replace('_', ' ')} - `}
{`Currently ${moment()
.tz(timeZone)
.format('h:MMa')}`}
)
}
/>
);
}
_renderPersonInfo() {
const { facebook, linkedin, twitter, employment, location, bio } = this.state.person || {};
return (
{this.props.contact.fullName() !== this.props.contact.email && (
{this.props.contact.fullName()}
)}
{employment && (
{employment.title && {employment.title}, }
{employment.name}
)}
{this.props.contact.email}
);
}
render() {
return (
{this._renderPersonInfo()}
{this._renderCompanyInfo()}
{this._renderFindCTA()}
);
}
}