Switch quick reply on/off, select viewed msg

master
Vitaliy Filippov 2016-06-22 13:37:40 +03:00
parent 62b30d6a39
commit 29e4ff8ff7
1 changed files with 94 additions and 26 deletions

120
mail.js
View File

@ -1,5 +1,8 @@
window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame;
var WeekDays = [ 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat' ];
var Months = [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ];
function getOffset(elem)
{
if (elem.getBoundingClientRect)
@ -30,16 +33,27 @@ function getOffset(elem)
var Store = {
layout: 'message-on-right',
quickReply: true,
msg: null,
listeners: {},
on: function(ev, cb)
{
this.listeners[ev] = this.listeners[ev] || [];
this.listeners[ev].push(cb);
},
setLayout: function(l)
un: function(ev, cb)
{
this.layout = l;
(this.listeners['setLayout'] || []).map(i => i());
if (!this.listeners[ev])
return;
for (var i = this.listeners[ev].length; i >= 0; i--)
if (this.listeners[ev] == cb)
this.listeners[ev].splice(i, 1);
},
set: function(k, v)
{
this[k] = v;
(this.listeners[k] || []).map(i => i());
}
};
@ -443,25 +457,35 @@ var MailSettingsWindow = React.createClass({
},
componentDidMount: function()
{
Store.on('setLayout', this.setLayout);
Store.on('layout', this.setLayout);
Store.on('quickReply', this.setQuickReply);
},
componentWillUnmount: function()
{
Store.un('layout', this.setLayout);
Store.un('quickReply', this.setQuickReply);
},
setLayout: function()
{
this.setState({ layout: Store.layout });
},
setQuickReply: function()
{
this.setState({ showQuickReply: Store.quickReply });
},
switchLayout: function(ev)
{
var t = ev.target.nodeName == 'A' ? ev.target : ev.target.parentNode;
var l = / mail-(\S+)/.exec(t.className)[1];
Store.setLayout(l);
Store.set('layout', l);
},
getInitialState: function()
{
return { showQuickReply: this.props.showQuickReply && true, layout: Store.layout };
return { showQuickReply: Store.quickReply, layout: Store.layout };
},
showQuickReply: function()
{
this.setState({ showQuickReply: !this.state.showQuickReply });
Store.set('quickReply', !this.state.showQuickReply);
}
});
@ -495,7 +519,6 @@ var dropdown_settings = React.createElement(
MailSettingsWindow, {
id: 'settings',
window: true,
showQuickReply: true,
markDelay: -1,
defaultSorting: {
sort: {
@ -686,7 +709,7 @@ function formatBytes(s)
function formatDate(dt)
{
if (!(dt instanceof Date))
dt = new Date(dt);
dt = new Date(dt.replace(' ', 'T'));
var tod = new Date();
tod.setHours(0);
tod.setMinutes(0);
@ -702,9 +725,7 @@ function formatDate(dt)
}
else if (dt.getTime() < tod.getTime())
{
var wd = [ 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat' ];
var mon = [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ];
return wd[dt.getDay()]+' '+dt.getDate()+' '+mon[dt.getMonth()];
return WeekDays[dt.getDay()]+' '+dt.getDate()+' '+Months[dt.getMonth()];
}
var h = dt.getHours();
var m = dt.getMinutes();
@ -807,10 +828,14 @@ var ComposeWindow = React.createClass({
var MessageInList = React.createClass({
msgClasses: [ 'unread', 'unseen', 'replied', 'pinned', 'sent', 'unloaded', 'selected' ],
onClick: function()
{
Store.set('msg', this.props.msg);
},
render: function()
{
var msg = this.props.msg;
return <div className={'message'+(this.msgClasses.map(c => (msg[c] ? ' '+c : '')).join(''))+(msg.thread ? ' thread0' : '')}>
return <div className={'message'+(this.msgClasses.map(c => (msg[c] ? ' '+c : '')).join(''))+(msg.thread ? ' thread0' : '')} onClick={this.onClick}>
<div className="icon" style={{ width: (20+10*(msg.level||0)), backgroundPosition: (10*(msg.level||0))+'px 7px' }}></div>
<div className="subject" style={{ paddingLeft: (20+10*(msg.level||0)) }}>{msg.subject}</div>
{msg.thread ? <div className={'expand'+(msg.collapsed ? '' : ' collapse')}></div> : null}
@ -818,7 +843,7 @@ var MessageInList = React.createClass({
<div className="from" style={{ left: (21+10*(msg.level||0)) }}>{(msg.sent || msg.outgoing ? 'To '+msg.to : msg.from)}</div>
<div className="size">{formatBytes(msg.size)}</div>
<div className="attach" style={msg.attach ? null : { display: 'none' }}></div>
<div className="time">{formatDate(msg.date)}</div>
<div className="time">{formatDate(msg.time)}</div>
</div>
}
});
@ -855,10 +880,10 @@ var MessageList = React.createClass({
i > 0 ? <div className="day">{grp.name}</div> : null,
<div className="day-list">
{grp.messages.map(msg => [
<MessageInList msg={msg} />,
<MessageInList msg={msg} onClick={this.onMsgClick} />,
(msg.thread ?
<div className="thread">
{msg.thread.map(reply => <MessageInList msg={reply} />)}
{msg.thread.map(reply => <MessageInList msg={reply} onClick={this.onMsgClick} />)}
</div>
: null)
])}
@ -866,17 +891,48 @@ var MessageList = React.createClass({
])}
</div>
</div>
},
onMsgClick: function(msg)
{
}
});
var MessageView = React.createClass({
formatLongTime: function(d)
formatLongDate: function(dt)
{
//Чт 09 июн 2016 21:10:50
if (!(dt instanceof Date))
dt = new Date(dt.replace(' ', 'T'));
var h = dt.getHours();
var m = dt.getMinutes();
var s = dt.getSeconds();
return WeekDays[dt.getDay()]+' '+dt.getDate()+' '+Months[dt.getMonth()]+' '+dt.getFullYear()+' '+(h < 10 ? '0' : '')+h+':'+(m < 10 ? '0' : '')+m+':'+(s < 10 ? '0' : '')+s
//return dt.toLocaleString();
},
componentDidMount: function()
{
Store.on('quickReply', this.setQuickReply);
Store.on('msg', this.setMsg);
},
componentWillUnmount: function()
{
Store.un('quickReply', this.setQuickReply);
Store.un('msg', this.setMsg);
},
setQuickReply: function()
{
this.setState({ quickReply: Store.quickReply });
},
setMsg: function()
{
this.setState({ msg: Store.msg });
},
getInitialState: function()
{
return { quickReply: Store.quickReply };
},
render: function()
{
var msg = this.props.msg;
var msg = this.state.msg;
return <div className={'message-view'+(!msg ? ' no-mail-shown' : '')}>
<div className="actions">
<DropDownButton dropdownId="reply" icon="mail_reply" text="Reply" />
@ -900,13 +956,13 @@ var MessageView = React.createClass({
<div className="headers">
<div className="top">
<div className="pin"></div>
<div className="time">{this.formatLongTime(msg.time)}</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.from}</a></div>
<div className="value"><a className="button">{msg.from+' <'+msg.fromEmail+'>'}></a></div>
</div>
<div className="header">
<div className="field">To</div>
@ -935,7 +991,8 @@ var MessageView = React.createClass({
<label><input type="checkbox" /> Always load from {msg.from}</label>
</div>
: null),
<div className="text" dangerouslySetInnerHTML={msg.body}></div>,
<div className="text" dangerouslySetInnerHTML={{ __html: msg.body }}></div>,
this.state.quickReply ?
<div className="quick-reply">
<textarea></textarea>
<div className="btns">
@ -943,6 +1000,7 @@ var MessageView = React.createClass({
<a className="button"><img src="icons/mail_reply_all.png" /> Quick Reply All</a>
</div>
</div>
: null
] : null}
</div>
}
@ -1010,13 +1068,19 @@ var listGroups = [ {
messages: [ {
subject: 'кошку хочешь?))',
sent: true,
from: 'Виталий Филиппов',
fromEmail: 'vitalif@mail.ru',
to: 'Margarita Philippova',
date: '2016-06-14 21:24',
time: '2016-06-14 21:24',
body: 'к нам тут пришла какая-то и к нам в дом рвётся, симпатишная) потеряшка какая-то, но явно домашняя, не боится людей))',
thread: [ {
subject: 'Re: кошку хочешь?))',
from: 'Margarita Philippova',
date: '2016-06-14 22:31',
level: 1
fromEmail: 'philippova.marga@gmail.com',
to: 'Виталий Филиппов',
time: '2016-06-14 22:31',
level: 1,
body: 'Нет, конечно, не хочу. Я уеду в Баку, а кошка как? Уеду в Астану - а кошка как? Наташа меня Сухорукова приглашает в Барселону - а кошку куда? Я только испытала радость облегчения от того, что у меня больше нет горшочных цветов - и кошку мне? НЕт! Папику предложи - у него уже много зверья, одной кошкой больше - одной меньше - какая разница?'
} ]
} ]
} ];
@ -1024,7 +1088,11 @@ var listGroups = [ {
var AllTabs = React.createClass({
componentDidMount: function()
{
Store.on('setLayout', this.setLayout);
Store.on('layout', this.setLayout);
},
componentWillUnmount: function()
{
Store.un('layout', this.setLayout);
},
setLayout: function()
{