Implement image/css blocking, fix "Settings" button migration and some errors
parent
6d2b3e2aa9
commit
ea874385c1
|
@ -2,9 +2,9 @@ const React = require('react');
|
|||
const DropDownBase = require('./DropDownBase.js');
|
||||
|
||||
var DropDownButton = module.exports = React.createClass({
|
||||
componentWillReceiveProps: function(nextProps)
|
||||
componentDidUpdate: function(prevProps, prevState)
|
||||
{
|
||||
if (!nextProps.hidden && this.props.hidden &&
|
||||
if (prevProps.hidden && !this.props.hidden &&
|
||||
DropDownBase.instances[this.props.dropdownId].isVisible())
|
||||
{
|
||||
DropDownBase.instances[this.props.dropdownId].showAt(this.refs.btn, this.unpress);
|
||||
|
@ -14,7 +14,7 @@ var DropDownButton = module.exports = React.createClass({
|
|||
{
|
||||
return <a ref="btn" title={(this.state.checked ? this.props.checkedTitle : null) || this.props.title} onClick={this.onClickButton}
|
||||
className={'button '+(this.props.dropdownId ? 'show-dropdown ' : '')+(this.state.checked ? 'checked ' : '')+
|
||||
(this.state.hidden ? 'hidden ' : '')+
|
||||
(this.props.hidden ? 'hidden ' : '')+
|
||||
(this.state.pressed ? 'pressed ' : '')+(this.props.className || '')}>
|
||||
{this.props.icon ? <img src={'icons/'+(this.state.checked && this.props.checkedIcon || this.props.icon)+'.png'} /> : null}
|
||||
{this.state.checked && this.props.checkedText || this.props.text || null}
|
||||
|
|
|
@ -21,7 +21,7 @@ var MailSettingsWindow = React.createClass({
|
|||
<div className="text">Default List Sorting</div>
|
||||
<ListSortSettings className="fields" sort={this.props.defaultSorting} />
|
||||
<div className="fields">
|
||||
<label><input type="checkbox" checked={this.props.showQuickReply} onClick={this.showQuickReply} /> Show Quick Reply</label>
|
||||
<label><input type="checkbox" checked={this.props.quickReply} onClick={this.showQuickReply} /> Show Quick Reply</label>
|
||||
</div>
|
||||
<div className="split"><i></i></div>
|
||||
<div className="text">Mark as Read</div>
|
||||
|
@ -44,13 +44,13 @@ var MailSettingsWindow = React.createClass({
|
|||
},
|
||||
showQuickReply: function()
|
||||
{
|
||||
Store.set('quickReply', !this.state.showQuickReply);
|
||||
Store.set('quickReply', !this.props.quickReply);
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = StoreListener(
|
||||
MailSettingsWindow,
|
||||
(data) => { return { layout: data.layout, showQuickReply: data.showQuickReply }; },
|
||||
(data) => { return { layout: data.layout, quickReply: data.quickReply }; },
|
||||
{
|
||||
id: 'settings',
|
||||
window: true,
|
||||
|
|
|
@ -38,7 +38,7 @@ var MessageList = React.createClass({
|
|||
setFirstDayFromProps: function(props)
|
||||
{
|
||||
var groups = props.groups;
|
||||
if (!groups.length)
|
||||
if (!groups || !groups.length)
|
||||
return;
|
||||
var scrollTop = this.refs.scroll.scrollTop, scrollSize = this.refs.scroll.offsetHeight - this.getScrollPaddingTop();
|
||||
var top = 0, p, firstVisibleGrp, firstVisible, lastVisibleGrp, lastVisible;
|
||||
|
@ -95,7 +95,7 @@ var MessageList = React.createClass({
|
|||
{
|
||||
var self = this;
|
||||
var total = 0, p, msg, idx;
|
||||
for (var i = 0; i < self.props.groups.length; i++)
|
||||
for (var i = 0; i < (self.props.groups||[]).length; i++)
|
||||
{
|
||||
p = total;
|
||||
total += (i > 0 ? 1 : 0)+self.props.groups[i].messageCount;
|
||||
|
@ -123,7 +123,7 @@ var MessageList = React.createClass({
|
|||
getTotalItems: function()
|
||||
{
|
||||
var total = -1; // do not count first-day as item
|
||||
for (var i = 0; i < this.props.groups.length; i++)
|
||||
for (var i = 0; i < (this.props.groups||[]).length; i++)
|
||||
{
|
||||
total += 1+this.props.groups[i].messageCount;
|
||||
}
|
||||
|
@ -136,7 +136,7 @@ var MessageList = React.createClass({
|
|||
getItemOffset: function(index)
|
||||
{
|
||||
var n = 0, top = this.refs.title.offsetHeight, p;
|
||||
for (var i = 0; i < this.props.groups.length; i++)
|
||||
for (var i = 0; i < (this.props.groups||[]).length; i++)
|
||||
{
|
||||
p = n;
|
||||
n += (i > 0 ? 1 : 0)+this.props.groups[i].messageCount;
|
||||
|
|
|
@ -15,9 +15,44 @@ var MessageView = React.createClass({
|
|||
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
|
||||
//return dt.toLocaleString();
|
||||
},
|
||||
componentWillReceiveProps: function(nextProps)
|
||||
{
|
||||
if (nextProps.msg != this.props.msg)
|
||||
{
|
||||
var ns = { showImages: false, blockedImages: false };
|
||||
if (/<img[^>]*>/i.exec(nextProps.msg.body_html))
|
||||
{
|
||||
ns.blockedImages = true;
|
||||
}
|
||||
this.setState(ns);
|
||||
}
|
||||
},
|
||||
showImages: function()
|
||||
{
|
||||
this.setState({ showImages: true });
|
||||
},
|
||||
getInitialState: function()
|
||||
{
|
||||
return { showImages: false };
|
||||
},
|
||||
render: function()
|
||||
{
|
||||
var showImages = this.state.showImages;
|
||||
var msg = this.props.msg;
|
||||
var 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" />
|
||||
|
@ -69,15 +104,15 @@ var MessageView = React.createClass({
|
|||
: null}
|
||||
</div>
|
||||
</div>,
|
||||
(msg.blockedImages
|
||||
(this.state.blockedImages && !this.state.showImages
|
||||
? <div className="blocked-images">
|
||||
<img src="icons/block.png" /> This message contains blocked images.
|
||||
<a className="button raised">Load Images</a>
|
||||
<label><input type="checkbox" /> Always load from {msg.from}</label>
|
||||
<a className="button raised" onClick={this.showImages}>Load Images</a>
|
||||
<label><input type="checkbox" /> Always load from {msg.from_email}</label>
|
||||
</div>
|
||||
: null),
|
||||
(msg.body_html
|
||||
? <div className="text" dangerouslySetInnerHTML={{ __html: msg.body_html }}></div>
|
||||
(html
|
||||
? <div className="text" dangerouslySetInnerHTML={{ __html: html }}></div>
|
||||
: <div className="text plain">{msg.body_text}</div>
|
||||
),
|
||||
(this.props.quickReply
|
||||
|
|
17
mail.css
17
mail.css
|
@ -137,6 +137,11 @@ div
|
|||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.show-dropdown.hidden
|
||||
{
|
||||
display: none;
|
||||
}
|
||||
|
||||
.show-dropdown .down
|
||||
{
|
||||
float: right;
|
||||
|
@ -753,13 +758,6 @@ div
|
|||
.message-list .actions .settings
|
||||
{
|
||||
float: right;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.message-on-bottom .message-list .actions .settings,
|
||||
.message-invisible .message-list .actions .settings
|
||||
{
|
||||
display: block;
|
||||
}
|
||||
|
||||
.message-list .listview
|
||||
|
@ -1178,11 +1176,6 @@ div
|
|||
border-bottom: 1px solid #aca9a7;
|
||||
}
|
||||
|
||||
.message-on-bottom .message-view .actions .settings
|
||||
{
|
||||
display: none;
|
||||
}
|
||||
|
||||
.message-view
|
||||
{
|
||||
display: flex;
|
||||
|
|
|
@ -81,3 +81,19 @@ a.button .img
|
|||
{
|
||||
content: "Undelete";
|
||||
}
|
||||
|
||||
.message-list .actions .settings
|
||||
{
|
||||
display: none;
|
||||
}
|
||||
|
||||
.message-on-bottom .message-list .actions .settings,
|
||||
.message-invisible .message-list .actions .settings
|
||||
{
|
||||
display: block;
|
||||
}
|
||||
|
||||
.message-on-bottom .message-view .actions .settings
|
||||
{
|
||||
display: none;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue