2015-11-07 07:53:21 +08:00
|
|
|
React = require 'react'
|
|
|
|
_ = require 'underscore'
|
2016-05-04 07:42:28 +08:00
|
|
|
EmailFrame = require('./email-frame').default
|
2017-02-18 06:12:51 +08:00
|
|
|
{encodedAttributeForFile} = require('./inline-image-listeners')
|
2016-10-04 02:22:28 +08:00
|
|
|
{
|
|
|
|
DraftHelpers,
|
|
|
|
CanvasUtils,
|
|
|
|
MessageUtils,
|
|
|
|
MessageBodyProcessor,
|
|
|
|
QuotedHTMLTransformer,
|
2017-06-29 13:45:15 +08:00
|
|
|
AttachmentStore
|
2016-10-04 02:22:28 +08:00
|
|
|
} = require 'nylas-exports'
|
2016-11-30 04:29:28 +08:00
|
|
|
{
|
|
|
|
InjectedComponentSet,
|
|
|
|
RetinaImg
|
|
|
|
} = require 'nylas-component-kit'
|
2015-11-07 07:53:21 +08:00
|
|
|
|
|
|
|
TransparentPixel = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR4nGNikAQAACIAHF/uBd8AAAAASUVORK5CYII="
|
|
|
|
|
|
|
|
class MessageItemBody extends React.Component
|
|
|
|
@displayName: 'MessageItemBody'
|
|
|
|
@propTypes:
|
|
|
|
message: React.PropTypes.object.isRequired
|
|
|
|
downloads: React.PropTypes.object.isRequired
|
|
|
|
|
|
|
|
constructor: (@props) ->
|
2016-09-21 06:17:45 +08:00
|
|
|
@_mounted = false
|
2015-11-07 07:53:21 +08:00
|
|
|
@state =
|
2016-05-19 07:19:42 +08:00
|
|
|
showQuotedText: DraftHelpers.isForwardedMessage(@props.message)
|
2016-03-10 10:01:13 +08:00
|
|
|
processedBody: null
|
2015-11-07 07:53:21 +08:00
|
|
|
|
|
|
|
componentWillMount: =>
|
2016-04-01 03:13:46 +08:00
|
|
|
@_unsub = MessageBodyProcessor.subscribe @props.message, (processedBody) =>
|
|
|
|
@setState({processedBody})
|
2016-03-10 10:01:13 +08:00
|
|
|
|
|
|
|
componentDidMount: =>
|
2016-09-21 06:17:45 +08:00
|
|
|
@_mounted = true
|
2015-11-07 07:53:21 +08:00
|
|
|
|
2016-03-09 05:06:54 +08:00
|
|
|
componentWillReceiveProps: (nextProps) ->
|
|
|
|
if nextProps.message.id isnt @props.message.id
|
|
|
|
@_unsub?()
|
2016-04-01 03:13:46 +08:00
|
|
|
@_unsub = MessageBodyProcessor.subscribe nextProps.message, (processedBody) =>
|
|
|
|
@setState({processedBody})
|
2015-11-19 04:32:07 +08:00
|
|
|
|
2015-11-07 07:53:21 +08:00
|
|
|
componentWillUnmount: =>
|
2016-09-21 06:17:45 +08:00
|
|
|
@_mounted = false
|
2015-11-07 07:53:21 +08:00
|
|
|
@_unsub?()
|
|
|
|
|
|
|
|
render: =>
|
|
|
|
<span>
|
|
|
|
<InjectedComponentSet
|
|
|
|
matching={role: "message:BodyHeader"}
|
|
|
|
exposedProps={message: @props.message}
|
|
|
|
direction="column"
|
|
|
|
style={width:'100%'}/>
|
|
|
|
{@_renderBody()}
|
|
|
|
{@_renderQuotedTextControl()}
|
|
|
|
</span>
|
|
|
|
|
|
|
|
_renderBody: =>
|
2016-03-11 08:13:17 +08:00
|
|
|
if _.isString(@props.message.body) and _.isString(@state.processedBody)
|
2016-05-03 06:59:14 +08:00
|
|
|
<EmailFrame
|
|
|
|
showQuotedText={@state.showQuotedText}
|
|
|
|
content={@_mergeBodyWithFiles(@state.processedBody)}
|
|
|
|
message={@props.message}
|
|
|
|
/>
|
2016-03-10 10:01:13 +08:00
|
|
|
else
|
|
|
|
<div className="message-body-loading">
|
|
|
|
<RetinaImg
|
|
|
|
name="inline-loading-spinner.gif"
|
|
|
|
mode={RetinaImg.Mode.ContentDark}
|
|
|
|
style={{width: 14, height: 14}}/>
|
|
|
|
</div>
|
2015-11-07 07:53:21 +08:00
|
|
|
|
|
|
|
_renderQuotedTextControl: =>
|
2015-12-08 07:34:03 +08:00
|
|
|
return null unless QuotedHTMLTransformer.hasQuotedHTML(@props.message.body)
|
2015-11-07 07:53:21 +08:00
|
|
|
<a className="quoted-text-control" onClick={@_toggleQuotedText}>
|
2016-03-22 09:22:20 +08:00
|
|
|
<span className="dots">•••</span>
|
2015-11-07 07:53:21 +08:00
|
|
|
</a>
|
|
|
|
|
|
|
|
_toggleQuotedText: =>
|
|
|
|
@setState
|
|
|
|
showQuotedText: !@state.showQuotedText
|
|
|
|
|
2016-04-01 03:13:46 +08:00
|
|
|
_mergeBodyWithFiles: (body) =>
|
2016-09-21 06:17:45 +08:00
|
|
|
# Replace cid: references with the paths to downloaded files
|
2015-11-07 07:53:21 +08:00
|
|
|
for file in @props.message.files
|
2015-12-08 07:00:20 +08:00
|
|
|
download = @props.downloads[file.id]
|
2016-09-27 07:59:43 +08:00
|
|
|
|
2016-10-04 02:22:28 +08:00
|
|
|
# Note: I don't like doing this with RegExp before the body is inserted into
|
|
|
|
# the DOM, but we want to avoid "could not load cid://" in the console.
|
2015-12-08 07:00:20 +08:00
|
|
|
|
|
|
|
if download and download.state isnt 'finished'
|
2017-01-08 08:03:19 +08:00
|
|
|
inlineImgRegexp = new RegExp("<\s*img.*src=['\"]cid:#{file.contentId}['\"][^>]*>", 'gi')
|
|
|
|
# Render a spinner
|
|
|
|
body = body.replace inlineImgRegexp, =>
|
|
|
|
'<img alt="spinner.gif" src="nylas://message-list/assets/spinner.gif" style="-webkit-user-drag: none;">'
|
2015-12-08 07:00:20 +08:00
|
|
|
else
|
2016-10-04 02:22:28 +08:00
|
|
|
# Render the completed download. We include data-nylas-file so that if the image fails
|
|
|
|
# to load, we can parse the file out and call `Actions.fetchFile` to retrieve it.
|
|
|
|
# (Necessary when attachment download mode is set to "manual")
|
2017-01-08 08:03:19 +08:00
|
|
|
cidRegexp = new RegExp("cid:#{file.contentId}(['\"])", 'gi')
|
2015-12-08 07:00:20 +08:00
|
|
|
body = body.replace cidRegexp, (text, quoteCharacter) ->
|
2017-06-29 13:45:15 +08:00
|
|
|
"file://#{AttachmentStore.pathForFile(file)}#{quoteCharacter} data-nylas-file=\"#{encodedAttributeForFile(file)}\" "
|
2015-11-07 07:53:21 +08:00
|
|
|
|
2016-09-21 06:17:45 +08:00
|
|
|
# Replace remaining cid: references - we will not display them since they'll
|
2015-11-07 07:53:21 +08:00
|
|
|
# throw "unknown ERR_UNKNOWN_URL_SCHEME". Show a transparent pixel so that there's
|
|
|
|
# no "missing image" region shown, just a space.
|
|
|
|
body = body.replace(MessageUtils.cidRegex, "src=\"#{TransparentPixel}\"")
|
|
|
|
|
2016-04-01 03:13:46 +08:00
|
|
|
return body
|
2015-11-07 07:53:21 +08:00
|
|
|
|
|
|
|
module.exports = MessageItemBody
|