likeopera-frontend/MessageView.js

159 lines
7.7 KiB
JavaScript

import React from 'react';
import DropDownButton from './DropDownButton.js';
import Util from './Util.js';
export default class MessageView extends React.PureComponent
{
state = { showImages: false }
formatLongDate(dt)
{
if (!(dt instanceof Date))
dt = new Date(dt.replace(' ', 'T'));
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;
}
componentWillReceiveProps(nextProps)
{
if (nextProps.msg != this.props.msg)
{
let ns = { showImages: false, blockedImages: false };
if (nextProps.msg && /<img[^>]*>/i.exec(nextProps.msg.body_html))
{
ns.blockedImages = true;
}
this.setState(ns);
}
}
showImages = () =>
{
this.setState({ showImages: true });
}
render()
{
let showImages = this.state.showImages;
let msg = this.props.msg;
let html;
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>';
});
}
}
return <div className={'message-view'+(!msg ? ' no-mail-shown' : '')+(!this.props.quickReply ? ' no-quick' : '')}>
<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"
checkable="1" checked={msg && !msg.flags.filter(f => f == 'unread').length}
checkedIcon="read_selected" icon="read"
checkedText="Unread" text="Read"
onClick={this.props.onToggleRead}
/>
<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>
<DropDownButton dropdownId="settings" whole="1" icon="config" text="Settings" hidden={this.props.layout != 'message-on-right'} />
</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>
<div className="value"><a className="button">{msg.props.from ? msg.props.from[0]+' <'+msg.props.from[1]+'>' : 'unknown'}</a></div>
</div>
<div className="header">
<div className="field">To</div>
<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>
</div>
{msg.props.cc.length
? <div className="header">
<div className="field">Cc</div>
<div className="value">
{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>)}
</div>
</div>
: null}
{msg.props.replyto
? <div className="header">
<div className="field">Reply-to</div>
<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.name} href={"backend/attachment/?msgId="+msg.id+"&sha1="+a.sha1} target="_blank">
{a.name+' ('+Util.formatBytes(a.size)+')'}
</a>
))}
</div>
</div>
: null}
</div>
</div>,
(this.state.blockedImages && !this.state.showImages
? <div className="blocked-images">
<img src="icons/block.png" /> This message contains blocked images.
<a className="button raised" onClick={this.showImages}>Load Images</a>
{(msg.props.from ? <label><input type="checkbox" /> Always load from {msg.props.from[1]}</label> : null)}
</div>
: null),
(html
? <div className="text" dangerouslySetInnerHTML={{ __html: html }}></div>
: <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),
] : null}
</div>
}
}