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 (