import { IdentityStore, FeatureUsageStore, React, PropTypes, DOMUtils, RegExpUtils, Utils, } from 'mailspring-exports'; import { RetinaImg } from 'mailspring-component-kit'; import ParticipantProfileDataSource from './participant-profile-data-source'; /* We expect ParticipantProfileDataSource.find to return the * following schema: * { * profilePhotoUrl: string * bio: string * location: string * currentTitle: string * currentEmployer: string * socialProfiles: hash keyed by type: ('twitter', 'facebook' etc) * url: string * handle: string * } */ 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.asyncUseFeature('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)); }); }; _renderProfilePhoto() { const hue = Utils.hueForString(this.props.contact.email); const bgColor = `hsl(${hue}, 50%, 45%)`; let content = (
{this.props.contact.nameAbbreviation()}
); if (this.state.loading) { content = (
); } if (this.state.profilePhotoUrl) { content = Profile; } return (
{content}
); } _renderCorePersonalInfo() { const fullName = this.props.contact.fullName(); let renderName = false; if (fullName !== this.props.contact.email) { renderName = (
{this.props.contact.fullName()}
); } return (
{renderName}
{this.props.contact.email}
{this._renderSocialProfiles()}
); } _renderSocialProfiles() { if (!this.state.socialProfiles) { return false; } const profiles = Object.entries(this.state.socialProfiles).map(([type, profile]) => { return ( ); }); return
{profiles}
; } _renderAdditionalInfo() { return (
{this._renderCurrentJob()} {this._renderBio()} {this._renderLocation()}
); } _renderCurrentJob() { if (!this.state.employer) { return false; } let title = false; if (this.state.title) { title = {this.state.title}, ; } return (

{title} {this.state.employer}

); } _renderBio() { if (!this.state.bio) { return false; } const bioNodes = []; const hashtagOrMentionRegex = RegExpUtils.hashtagOrMentionRegex(); let bioRemainder = this.state.bio; let match = null; let count = 0; /* I thought we were friends. */ /* eslint no-cond-assign: 0 */ while ((match = hashtagOrMentionRegex.exec(bioRemainder))) { // the first char of the match is whitespace, match[1] is # or @, match[2] is the tag itself. bioNodes.push(bioRemainder.substr(0, match.index + 1)); if (match[1] === '#') { bioNodes.push( {`#${match[2]}`} ); } if (match[1] === '@') { bioNodes.push({`@${match[2]}`}); } bioRemainder = bioRemainder.substr(match.index + match[0].length); count += 1; } bioNodes.push(bioRemainder); return

{bioNodes}

; } _renderLocation() { if (!this.state.location) { return false; } return (

{this.state.location}

); } _select(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...`}
); } render() { return (
{this._renderProfilePhoto()} {this._renderCorePersonalInfo()} {this._renderAdditionalInfo()} {this._renderFindCTA()}
); } }