Implement image/css blocking, fix "Settings" button migration and some errors

master
Vitaliy Filippov 2016-10-03 13:18:11 +03:00
parent 6d2b3e2aa9
commit ea874385c1
6 changed files with 71 additions and 27 deletions

View File

@ -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}

View File

@ -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,

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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;
}