2018-12-02 19:27:22 +03:00
|
|
|
import React from 'react';
|
|
|
|
import DropDownButton from './DropDownButton.js';
|
|
|
|
import Store from './Store.js';
|
|
|
|
import StoreListener from './StoreListener.js';
|
|
|
|
import Util from './Util.js';
|
2016-09-11 15:49:57 +03:00
|
|
|
|
2018-12-02 19:27:22 +03:00
|
|
|
class MessageView extends React.PureComponent
|
|
|
|
{
|
|
|
|
state = { showImages: false }
|
|
|
|
|
|
|
|
formatLongDate(dt)
|
2016-09-11 15:49:57 +03:00
|
|
|
{
|
|
|
|
if (!(dt instanceof Date))
|
|
|
|
dt = new Date(dt.replace(' ', 'T'));
|
2019-05-14 13:57:17 +03:00
|
|
|
let h = dt.getHours();
|
|
|
|
let m = dt.getMinutes();
|
|
|
|
let s = dt.getSeconds();
|
|
|
|
return Util.WeekDays[dt.getDay()]+' '+dt.getDate()+' '+Util.Months[dt.getMonth()]+' '+
|
|
|
|
dt.getFullYear()+' '+(h < 10 ? '0' : '')+h+':'+(m < 10 ? '0' : '')+m+':'+(s < 10 ? '0' : '')+s;
|
2018-12-02 19:27:22 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
componentWillReceiveProps(nextProps)
|
2016-10-03 13:18:11 +03:00
|
|
|
{
|
|
|
|
if (nextProps.msg != this.props.msg)
|
|
|
|
{
|
2019-05-14 13:57:17 +03:00
|
|
|
let ns = { showImages: false, blockedImages: false };
|
|
|
|
if (nextProps.msg && /<img[^>]*>/i.exec(nextProps.msg.body_html))
|
2016-10-03 13:18:11 +03:00
|
|
|
{
|
|
|
|
ns.blockedImages = true;
|
|
|
|
}
|
|
|
|
this.setState(ns);
|
|
|
|
}
|
2018-12-02 19:27:22 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
showImages = () =>
|
2016-10-03 13:18:11 +03:00
|
|
|
{
|
|
|
|
this.setState({ showImages: true });
|
2018-12-02 19:27:22 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
render()
|
2016-09-11 15:49:57 +03:00
|
|
|
{
|
2019-05-14 13:57:17 +03:00
|
|
|
let showImages = this.state.showImages;
|
|
|
|
let msg = this.props.msg;
|
|
|
|
let html;
|
2016-10-03 13:18:11 +03:00
|
|
|
if (msg)
|
|
|
|
{
|
|
|
|
html = msg.body_html;
|
|
|
|
if (!showImages)
|
|
|
|
{
|
|
|
|
html = html.replace(/(<img[^>]*?src=)(["'])([^'"]*\2)/ig, '$1$2blocked:$3');
|
|
|
|
html = html.replace(/<style[^>]*>(.*)<\/style\s*>/ig, function(m, m1)
|
|
|
|
{
|
|
|
|
m1 = m1.replace(/(url\(["']?|\@import\s*["'])([^"']*)/ig, '$1blocked:$2');
|
|
|
|
return '<style>'+m1+'</style>';
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
2016-10-01 17:21:32 +03:00
|
|
|
return <div className={'message-view'+(!msg ? ' no-mail-shown' : '')+(!this.props.quickReply ? ' no-quick' : '')}>
|
2016-09-11 15:49:57 +03:00
|
|
|
<div className="actions">
|
|
|
|
<DropDownButton dropdownId="reply" icon="mail_reply" text="Reply" />
|
|
|
|
<a className="button"><img src="icons/mail_reply_all.png" />Reply All</a>
|
|
|
|
<DropDownButton dropdownId="forward" icon="mail_forward" text="Forward" />
|
|
|
|
<DropDownButton className="action-read" icon="read" checkedIcon="read_selected" checkable="1" text="Read" checkedText="Unread" />
|
|
|
|
<DropDownButton className="action-spam" icon="spam" checkedIcon="spam_selected" checkable="1" text="Spam" checkedText="Not Spam" />
|
|
|
|
<DropDownButton dropdownId="delete" className="action-delete" icon="delete" checkedIcon="delete_selected" checkable="1" text="Delete" checkedText="Undelete" />
|
|
|
|
<a className="button show-dropdown"><img src="icons/label.png" />Label <span className="down"></span></a>
|
2016-10-01 23:59:02 +03:00
|
|
|
<DropDownButton dropdownId="settings" whole="1" icon="config" text="Settings" hidden={this.props.layout != 'message-on-right'} />
|
2016-09-11 15:49:57 +03:00
|
|
|
</div>
|
|
|
|
<div className="nomail">
|
|
|
|
<div className="flex1"></div>
|
|
|
|
<div className="middle">
|
|
|
|
<img src="icons/no_mail.png" />
|
|
|
|
<div className="txt">No message selected</div>
|
|
|
|
</div>
|
|
|
|
<div className="flex1"></div>
|
|
|
|
</div>
|
|
|
|
{msg ? [
|
|
|
|
<div className="headers">
|
|
|
|
<div className="top">
|
|
|
|
<div className="pin"></div>
|
|
|
|
<div className="time">{this.formatLongDate(msg.time)}</div>
|
|
|
|
<div className="subject">{msg.subject}</div>
|
|
|
|
</div>
|
|
|
|
<div className="header-table">
|
|
|
|
<div className="header">
|
|
|
|
<div className="field">From</div>
|
2016-10-05 13:52:02 +03:00
|
|
|
<div className="value"><a className="button">{msg.props.from ? msg.props.from[0]+' <'+msg.props.from[1]+'>' : 'unknown'}</a></div>
|
2016-09-11 15:49:57 +03:00
|
|
|
</div>
|
|
|
|
<div className="header">
|
|
|
|
<div className="field">To</div>
|
2016-10-05 13:52:02 +03:00
|
|
|
<div className="value">
|
|
|
|
{msg.props.to.map(a => <a className="button" title={a[0] ? a[0]+' <'+a[1]+'>' : a[1]}>{a[0] || a[1]}</a>)}
|
|
|
|
</div>
|
2016-09-11 15:49:57 +03:00
|
|
|
</div>
|
2016-10-05 13:52:02 +03:00
|
|
|
{msg.props.cc.length ?
|
2016-09-11 15:49:57 +03:00
|
|
|
<div className="header">
|
|
|
|
<div className="field">Cc</div>
|
|
|
|
<div className="value">
|
2016-10-05 13:52:02 +03:00
|
|
|
{msg.props.cc.map(a => <a className="button" title={a[0] ? a[0]+' <'+a[1]+'>' : a[1]}>{a[0] || a[1]}</a>)}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
: null}
|
|
|
|
{msg.props.bcc.length ?
|
|
|
|
<div className="header">
|
|
|
|
<div className="field">Bcc</div>
|
|
|
|
<div className="value">
|
|
|
|
{msg.props.bcc.map(a => <a className="button" title={a[0] ? a[0]+' <'+a[1]+'>' : a[1]}>{a[0] || a[1]}</a>)}
|
2016-09-11 15:49:57 +03:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
: null}
|
2016-10-05 13:52:02 +03:00
|
|
|
{msg.props.replyto ?
|
2016-09-11 15:49:57 +03:00
|
|
|
<div className="header">
|
|
|
|
<div className="field">Reply-to</div>
|
2016-10-09 17:49:30 +03:00
|
|
|
<div className="value">
|
|
|
|
{[msg.props.replyto].map(a => <a className="button" title={a[0] ? a[0]+' <'+a[1]+'>' : a[1]}>{a[0] || a[1]}</a>)}
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
: null}
|
|
|
|
{msg.props.attachments && msg.props.attachments.length ?
|
|
|
|
<div className="header">
|
|
|
|
<div className="field">Attachments</div>
|
|
|
|
<div className="value">
|
|
|
|
{msg.props.attachments.map(a => <a className="button" title={a[0]}>{a[0]+' ('+Util.formatBytes(a[2])+')'}</a>)}
|
|
|
|
</div>
|
2016-09-11 15:49:57 +03:00
|
|
|
</div>
|
|
|
|
: null}
|
|
|
|
</div>
|
|
|
|
</div>,
|
2016-10-03 13:18:11 +03:00
|
|
|
(this.state.blockedImages && !this.state.showImages
|
2016-10-02 22:12:53 +03:00
|
|
|
? <div className="blocked-images">
|
|
|
|
<img src="icons/block.png" /> This message contains blocked images.
|
2016-10-03 13:18:11 +03:00
|
|
|
<a className="button raised" onClick={this.showImages}>Load Images</a>
|
2016-10-05 13:52:02 +03:00
|
|
|
{(msg.props.from ? <label><input type="checkbox" /> Always load from {msg.props.from[1]}</label> : null)}
|
2016-09-11 15:49:57 +03:00
|
|
|
</div>
|
2016-10-02 22:12:53 +03:00
|
|
|
: null),
|
2016-10-03 13:18:11 +03:00
|
|
|
(html
|
|
|
|
? <div className="text" dangerouslySetInnerHTML={{ __html: html }}></div>
|
2016-10-02 22:12:53 +03:00
|
|
|
: <div className="text plain">{msg.body_text}</div>
|
|
|
|
),
|
|
|
|
(this.props.quickReply
|
|
|
|
? <div className="quick-reply">
|
|
|
|
<textarea></textarea>
|
|
|
|
<div className="btns">
|
|
|
|
<a className="button"><img src="icons/mail_send.png" /> Quick Reply</a>
|
|
|
|
<a className="button"><img src="icons/mail_reply_all.png" /> Quick Reply All</a>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
: null
|
|
|
|
)
|
2016-09-11 15:49:57 +03:00
|
|
|
] : null}
|
|
|
|
</div>
|
|
|
|
}
|
2018-12-02 19:27:22 +03:00
|
|
|
}
|
2016-10-01 17:21:32 +03:00
|
|
|
|
2018-12-02 19:27:22 +03:00
|
|
|
export default StoreListener(MessageView, (data) => { return { layout: data.layout, quickReply: data.quickReply, msg: data.msg }; });
|