import React from 'react'; import PropTypes from 'prop-types'; import classNames from 'classnames'; import { Utils, Actions, AttachmentStore } from 'mailspring-exports'; import { RetinaImg, InjectedComponentSet, InjectedComponent } from 'mailspring-component-kit'; import MessageParticipants from './message-participants'; import MessageItemBody from './message-item-body'; import MessageTimestamp from './message-timestamp'; import MessageControls from './message-controls'; export default class MessageItem extends React.Component { static displayName = 'MessageItem'; static propTypes = { thread: PropTypes.object.isRequired, message: PropTypes.object.isRequired, messages: PropTypes.array.isRequired, collapsed: PropTypes.bool, pending: PropTypes.bool, isMostRecent: PropTypes.bool, className: PropTypes.string, }; constructor(props, context) { super(props, context); const fileIds = this.props.message.fileIds(); this.state = { // Holds the downloadData (if any) for all of our files. It's a hash // keyed by a fileId. The value is the downloadData. downloads: AttachmentStore.getDownloadDataForFiles(fileIds), filePreviewPaths: AttachmentStore.previewPathsForFiles(fileIds), detailedHeaders: false, detailedHeadersTogglePos: { top: 18 }, }; } componentDidMount() { this._storeUnlisten = AttachmentStore.listen(this._onDownloadStoreChange); this._setDetailedHeadersTogglePos(); } shouldComponentUpdate(nextProps, nextState) { return !Utils.isEqualReact(nextProps, this.props) || !Utils.isEqualReact(nextState, this.state); } componentDidUpdate() { this._setDetailedHeadersTogglePos(); } componentWillUnmount() { if (this._storeUnlisten) { this._storeUnlisten(); } } _onClickParticipants = e => { let el = e.target; while (el !== e.currentTarget) { if (el.classList.contains('collapsed-participants')) { this.setState({ detailedHeaders: true }); e.stopPropagation(); return; } el = el.parentElement; } return; }; _onClickHeader = e => { if (this.state.detailedHeaders) { return; } let el = e.target; while (el !== e.currentTarget) { if ( el.classList.contains('message-header-right') || el.classList.contains('collapsed-participants') ) { return; } el = el.parentElement; } this._onToggleCollapsed(); }; _onDownloadAll = () => { Actions.fetchAndSaveAllFiles(this.props.message.files); }; _setDetailedHeadersTogglePos = () => { if (!this._headerEl) { return; } const fromNode = this._headerEl.querySelector( '.participant-name.from-contact,.participant-primary' ); if (!fromNode) { return; } const fromRect = fromNode.getBoundingClientRect(); const topPos = Math.floor(fromNode.offsetTop + fromRect.height / 2 - 10); if (topPos !== this.state.detailedHeadersTogglePos.top) { this.setState({ detailedHeadersTogglePos: { top: topPos } }); } }; _onToggleCollapsed = () => { if (this.props.isMostRecent) { return; } Actions.toggleMessageIdExpanded(this.props.message.id); }; _isRealFile = file => { const hasCIDInBody = file.contentId !== undefined && this.props.message.body && this.props.message.body.indexOf(file.contentId) > 0; return !hasCIDInBody; }; _onDownloadStoreChange = () => { const fileIds = this.props.message.fileIds(); this.setState({ downloads: AttachmentStore.getDownloadDataForFiles(fileIds), filePreviewPaths: AttachmentStore.previewPathsForFiles(fileIds), }); }; _renderDownloadAllButton() { return (
{this.props.message.files.length} attachments
-
Download all
); } _renderAttachments() { const files = (this.props.message.files || []).filter(f => this._isRealFile(f)); const messageId = this.props.message.id; const { filePreviewPaths, downloads } = this.state; if (files.length === 0) { return
; } return (
{files.length > 1 ? this._renderDownloadAllButton() : null}
); } _renderFooterStatus() { return ( ); } _renderHeader() { const { message, thread, messages, pending } = this.props; const classes = classNames({ 'message-header': true, pending: pending, }); return (
{ this._headerEl = el; }} className={classes} onClick={this._onClickHeader} >
{this._renderFolder()} {this._renderHeaderDetailToggle()}
); } _renderHeaderDetailToggle() { if (this.props.pending) { return null; } const { top } = this.state.detailedHeadersTogglePos; if (this.state.detailedHeaders) { return (
{ this.setState({ detailedHeaders: false }); e.stopPropagation(); }} >
); } return (
{ this.setState({ detailedHeaders: true }); e.stopPropagation(); }} >
); } _renderFolder() { if (!this.state.detailedHeaders) { return false; } const folder = this.props.message.folder; if (!folder || folder.role === 'al') { return false; } return (
Folder: 
{folder.displayName}
); } _renderCollapsed() { const { message: { snippet, from, files, date, draft }, className } = this.props; const attachmentIcon = Utils.showIconForAttachments(files) ? (
) : null; return (
{from && from[0] && from[0].displayName({ compact: true })}
{snippet}
{draft && (
)}
{attachmentIcon}
); } _renderFull() { return (
{this._renderHeader()} {this._renderAttachments()} {this._renderFooterStatus()}
); } render() { return this.props.collapsed ? this._renderCollapsed() : this._renderFull(); } }