2016-06-22 00:50:07 +03:00
window . requestAnimationFrame = window . requestAnimationFrame || window . mozRequestAnimationFrame ;
2016-06-22 13:37:40 +03:00
var WeekDays = [ 'Sun' , 'Mon' , 'Tue' , 'Wed' , 'Thu' , 'Fri' , 'Sat' ] ;
var Months = [ 'Jan' , 'Feb' , 'Mar' , 'Apr' , 'May' , 'Jun' , 'Jul' , 'Aug' , 'Sep' , 'Oct' , 'Nov' , 'Dec' ] ;
2016-06-21 16:57:33 +03:00
function getOffset ( elem )
{
if ( elem . getBoundingClientRect )
{
var box = elem . getBoundingClientRect ( ) ;
var body = document . body ;
var docElem = document . documentElement ;
var scrollTop = window . pageYOffset || docElem . scrollTop || body . scrollTop ;
var scrollLeft = window . pageXOffset || docElem . scrollLeft || body . scrollLeft ;
var clientTop = docElem . clientTop || body . clientTop || 0 ;
var clientLeft = docElem . clientLeft || body . clientLeft || 0 ;
var top = box . top + scrollTop - clientTop ;
var left = box . left + scrollLeft - clientLeft ;
return { top : Math . round ( top ) , left : Math . round ( left ) } ;
}
else
{
var top = 0 , left = 0 ;
while ( elem )
{
top = top + parseInt ( elem . offsetTop ) ;
left = left + parseInt ( elem . offsetLeft ) ;
elem = elem . offsetParent ;
}
return { top : top , left : left } ;
}
}
2016-06-22 00:14:07 +03:00
var Store = {
layout : 'message-on-right' ,
2016-06-22 13:37:40 +03:00
quickReply : true ,
msg : null ,
2016-06-23 01:17:22 +03:00
threads : false ,
2016-06-22 13:37:40 +03:00
2016-06-22 00:14:07 +03:00
listeners : { } ,
on : function ( ev , cb )
{
this . listeners [ ev ] = this . listeners [ ev ] || [ ] ;
this . listeners [ ev ] . push ( cb ) ;
} ,
2016-06-22 13:37:40 +03:00
un : function ( ev , cb )
{
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 )
2016-06-22 00:14:07 +03:00
{
2016-06-22 13:37:40 +03:00
this [ k ] = v ;
( this . listeners [ k ] || [ ] ) . map ( i => i ( ) ) ;
2016-06-22 00:14:07 +03:00
}
} ;
2016-06-21 16:57:33 +03:00
var DropDownBase = {
instances : { } ,
2016-06-22 01:01:37 +03:00
currentVisible : null ,
2016-06-21 16:57:33 +03:00
componentDidMount : function ( )
{
if ( ! DropDownBase . setBodyListener )
{
window . addEventListener ( 'click' , DropDownBase . hideAll ) ;
2016-06-22 01:01:37 +03:00
window . addEventListener ( 'resize' , DropDownBase . repositionCurrent ) ;
2016-06-21 16:57:33 +03:00
DropDownBase . setBodyListener = true ;
}
DropDownBase . instances [ this . props . id ] = this ;
} ,
hideAll : function ( )
{
for ( var i in DropDownBase . instances )
2016-06-21 22:55:28 +03:00
DropDownBase . instances [ i ] . hide ( ) ;
2016-06-21 16:57:33 +03:00
} ,
2016-06-22 01:01:37 +03:00
repositionCurrent : function ( )
{
if ( DropDownBase . currentVisible )
DropDownBase . currentVisible [ 0 ] . showAt ( DropDownBase . currentVisible [ 1 ] , DropDownBase . currentVisible [ 0 ] . onClose ) ;
} ,
2016-06-21 16:57:33 +03:00
componentWillUnmount : function ( )
{
delete DropDownBase . instances [ this . props . id ] ;
2016-06-22 01:01:37 +03:00
if ( DropDownBase . currentVisible [ 0 ] == this )
DropDownBase . currentVisible = null ;
2016-06-21 16:57:33 +03:00
} ,
getInitialState : function ( )
{
return { visible : false , top : 0 , left : 0 , calloutLeft : null , selectedItem : - 1 } ;
} ,
onClick : function ( ev )
{
ev . stopPropagation ( ) ;
} ,
hide : function ( )
{
this . setState ( { visible : false } ) ;
2016-06-22 01:01:37 +03:00
DropDownBase . currentVisible = null ;
2016-06-21 22:55:28 +03:00
if ( this . onClose )
{
this . onClose ( ) ;
delete this . onClose ;
}
2016-06-21 16:57:33 +03:00
} ,
2016-06-21 22:55:28 +03:00
showAt : function ( el , onClose )
2016-06-21 16:57:33 +03:00
{
2016-06-22 01:01:37 +03:00
if ( this . onClose && this . onClose != onClose )
2016-06-21 22:55:28 +03:00
{
this . onClose ( ) ;
delete this . onClose ;
}
2016-06-22 01:01:37 +03:00
DropDownBase . currentVisible = [ this , el ] ;
2016-06-21 16:57:33 +03:00
var p = getOffset ( el ) ;
var left = p . left , top = p . top + el . offsetHeight , calloutLeft = null ;
this . setState ( { visible : true , top : top , left : left , selectedItem : - 1 } ) ;
this . refs . dd . style . display = 'block' ;
if ( this . props . window )
{
left = Math . round ( p . left + el . offsetWidth / 2 - this . refs . dd . offsetWidth / 2 ) ;
top = p . top + el . offsetHeight + 3 ;
}
var ww = window . innerWidth || de . clientWidth || db . clientWidth ;
var wh = window . innerHeight || de . clientHeight || db . clientHeight ;
if ( left + this . refs . dd . offsetWidth > ww )
{
left = ww - this . refs . dd . offsetWidth ;
calloutLeft = Math . round ( p . left + el . offsetWidth / 2 - left ) ;
}
if ( top + this . refs . dd . offsetHeight > wh )
top = wh - this . refs . dd . offsetHeight ;
2016-06-22 16:16:57 +03:00
this . refs . dd . style . display = '' ;
2016-06-21 16:57:33 +03:00
this . setState ( { visible : true , top : top , left : left , calloutLeft : calloutLeft } ) ;
this . refs . dd . focus ( ) ;
2016-06-21 22:55:28 +03:00
this . onClose = onClose ;
2016-06-21 16:57:33 +03:00
}
} ;
2016-06-20 23:11:04 +03:00
var DropDownMenu = React . createClass ( {
2016-06-21 16:57:33 +03:00
mixins : [ DropDownBase ] ,
2016-06-21 22:55:28 +03:00
getInitialState : function ( )
{
return { items : this . props . items } ;
} ,
2016-06-20 01:42:23 +03:00
render : function ( )
{
2016-06-21 16:57:33 +03:00
var sel = this . state . selectedItem ;
return < div ref = "dd" className = { 'dropdown' + ( this . state . visible ? ' visible' : '' ) } id = { 'dropdown-' + this . props . id }
tabIndex = "1" style = { { top : this . state . top , left : this . state . left } } onClick = { this . myOnClick } onKeyDown = { this . onKeyDown }
onMouseOver = { this . onMouseOver } >
2016-06-21 22:55:28 +03:00
{ this . state . items . map ( function ( i , index ) {
2016-06-20 01:42:23 +03:00
return ( i . split
2016-06-20 23:11:04 +03:00
? < div key = { index } className = "split" > < i > < / i > < / d i v > :
2016-06-21 16:57:33 +03:00
< div key = { index } data - index = { index } className = { 'item' + ( i . i16 ? ' i16' : '' ) + ( i . disabled ? ' disabled' : ( sel == index ? ' over' : '' ) ) } >
2016-06-20 23:11:04 +03:00
{ i . hotkey ? < div className = "hotkey" > { i . hotkey } < / d i v > : n u l l }
2016-06-20 01:42:23 +03:00
{ i . icon ? < img src = { 'icons/' + i . icon + '.png' } / > : null }
< span > { i . text } < / s p a n >
< / d i v >
) ;
} ) }
< / d i v >
2016-06-21 16:57:33 +03:00
} ,
onMouseOver : function ( ev )
{
var t = ev . target ;
while ( ( t && t != this . refs . dd ) && ( ! t . className || t . className . substr ( 0 , 4 ) != 'item' ) )
t = t . parentNode ;
if ( t && t != this . refs . dd )
this . setState ( { selectedItem : parseInt ( t . getAttribute ( 'data-index' ) ) } ) ;
} ,
onKeyDown : function ( ev )
{
if ( ev . keyCode == 40 || ev . keyCode == 38 )
{
2016-06-21 22:55:28 +03:00
var a = ev . keyCode == 40 ? 1 : this . state . items . length - 1 ;
2016-06-21 16:57:33 +03:00
var sel = this . state . selectedItem ;
do
{
2016-06-21 22:55:28 +03:00
sel = ( ( sel + a ) % this . state . items . length ) ;
2016-06-21 16:57:33 +03:00
}
2016-06-21 22:55:28 +03:00
while ( this . state . items [ sel ] . split && sel != this . state . selectedItem ) ;
2016-06-21 16:57:33 +03:00
this . setState ( { selectedItem : sel } ) ;
}
else if ( ev . keyCode == 10 || ev . keyCode == 13 )
this . clickItem ( ) ;
ev . preventDefault ( ) ;
ev . stopPropagation ( ) ;
} ,
clickItem : function ( ev )
{
} ,
myOnClick : function ( ev )
{
if ( ev . target . getAttribute ( 'data-index' ) )
this . clickItem ( ) ;
this . onClick ( ev ) ;
}
} ) ;
var DropDownButton = React . createClass ( {
render : function ( )
{
2016-06-21 18:31:21 +03:00
return < a ref = "btn" title = { ( this . state . checked ? this . props . checkedTitle : null ) || this . props . title } onClick = { this . onClickButton }
2016-06-21 21:38:21 +03:00
className = { 'button ' + ( this . props . dropdownId ? 'show-dropdown ' : '' ) + ( this . state . checked ? 'checked ' : '' ) +
2016-06-21 18:31:21 +03:00
( this . state . pressed ? 'pressed ' : '' ) + ( this . props . className || '' ) } >
2016-06-21 21:47:41 +03:00
{ 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 }
2016-06-21 21:38:21 +03:00
{ this . props . dropdownId ? < span className = "down" onClick = { this . onClickDown } > < / s p a n > : n u l l }
2016-06-21 16:57:33 +03:00
< / a >
} ,
getInitialState : function ( )
{
2016-06-21 18:31:21 +03:00
return { pressed : false , checked : false } ;
2016-06-21 16:57:33 +03:00
} ,
toggle : function ( )
{
if ( ! this . state . pressed )
2016-06-21 21:38:21 +03:00
{
DropDownBase . hideAll ( ) ;
2016-06-22 20:24:06 +03:00
DropDownBase . instances [ this . props . dropdownId ] . showAt ( this . refs . btn , this . unpress ) ;
2016-06-21 21:38:21 +03:00
}
else
DropDownBase . instances [ this . props . dropdownId ] . hide ( ) ;
2016-06-21 16:57:33 +03:00
this . setState ( { pressed : ! this . state . pressed } ) ;
2016-06-22 20:24:06 +03:00
} ,
unpress : function ( )
{
this . setState ( { pressed : false } ) ;
2016-06-21 16:57:33 +03:00
} ,
onClickButton : function ( ev )
{
2016-06-21 21:38:21 +03:00
if ( this . props . whole || this . props . checkable && this . state . pressed )
2016-06-21 16:57:33 +03:00
this . toggle ( ) ;
2016-06-21 21:38:21 +03:00
if ( this . props . checkable )
2016-06-21 18:31:21 +03:00
this . setState ( { checked : ! this . state . checked } ) ;
2016-06-21 16:57:33 +03:00
ev . stopPropagation ( ) ;
} ,
onClickDown : function ( ev )
{
this . toggle ( ) ;
ev . stopPropagation ( ) ;
2016-06-20 01:42:23 +03:00
}
} ) ;
2016-06-20 23:11:04 +03:00
var dropdown _account = React . createElement (
2016-06-20 01:42:23 +03:00
DropDownMenu , {
id : 'account' ,
items : [ {
icon : 'mail_unread' ,
i16 : true ,
text : 'Read vitalif@mail.ru'
} , {
icon : 'folder' ,
text : 'IMAP Folders' ,
} , {
icon : 'properties' ,
text : 'Properties...'
} ]
}
) ;
2016-06-20 23:11:04 +03:00
var dropdown _reply = React . createElement (
2016-06-20 01:42:23 +03:00
DropDownMenu , {
id : 'reply' ,
items : [ {
hotkey : 'R' ,
icon : 'mail_reply' ,
text : 'Reply'
} , {
icon : 'mail_reply' ,
text : 'Reply to Sender' ,
} , {
disabled : true ,
icon : 'mail_reply_all' ,
text : 'Reply to List'
} ]
}
) ;
2016-06-20 23:11:04 +03:00
var dropdown _forward = React . createElement (
2016-06-20 01:42:23 +03:00
DropDownMenu , {
id : 'forward' ,
items : [ {
hotkey : 'F' ,
icon : 'mail_forward' ,
text : 'Reply'
} , {
hotkey : 'D' ,
text : 'Redirect'
} ]
}
) ;
2016-06-20 23:11:04 +03:00
var dropdown _delete = React . createElement (
2016-06-20 01:42:23 +03:00
DropDownMenu , {
id : 'delete' ,
items : [ {
text : 'Move to Trash'
} , {
icon : 'delete' ,
text : 'Delete Permanently'
} ]
}
) ;
2016-06-20 23:11:04 +03:00
var dropdown _check _send = React . createElement (
2016-06-20 01:42:23 +03:00
DropDownMenu , {
id : 'check-send' ,
items : [ {
hotkey : 'Ctrl-K' ,
icon : 'mail_check' ,
text : 'Check All'
} , {
hotkey : 'Ctrl-Shift-K' ,
icon : 'mail_send' ,
text : 'Send Queued'
} , { split : true } , {
icon : 'mail_check' ,
text : 'vitalif@mail.ru'
} , {
icon : 'mail_check' ,
text : 'vitalif@yourcmc.ru'
} , { split : true } , {
text : 'Resynchronize All Messages'
} ]
}
) ;
2016-06-20 23:11:04 +03:00
var dropdown _threads = React . createElement (
2016-06-20 01:42:23 +03:00
DropDownMenu , {
id : 'threads' ,
items : [ {
icon : 'thread' ,
text : 'Show Message Thread'
} , {
text : 'Follow Thread'
} , {
text : 'Ignore Thread'
} , { split : true } , {
hotkey : 'M' ,
icon : 'read' ,
text : 'Mark Thread as Read'
} , { split : true } , {
hotkey : 'N' ,
text : 'Mark Thread and Go to Next Unread'
} ]
}
) ;
2016-06-20 23:11:04 +03:00
var ListSortSettings = React . createClass ( {
2016-06-20 01:42:23 +03:00
render : function ( )
{
2016-06-23 01:17:22 +03:00
return < div className = { this . props . className } value = { this . props . sort . sortby } >
2016-06-20 23:11:04 +03:00
< select className = "sortby" >
2016-06-20 01:42:23 +03:00
{ [ 'sent date' , 'status' , 'label' , 'size' , 'subject' ] . map ( function ( i ) {
2016-06-23 01:17:22 +03:00
return < option key = { 's' + i } value = { i } > Sort by { i } < / o p t i o n >
2016-06-20 01:42:23 +03:00
} ) }
< / s e l e c t >
2016-06-23 01:17:22 +03:00
< select className = "group" value = { this . props . sort . group } >
< option value = "" > Do not group < / o p t i o n >
< option value = "read" > Group by read status < / o p t i o n >
< option value = "pinned" > Group by pinned status < / o p t i o n >
< option value = "date" > Group by date < / o p t i o n >
2016-06-20 01:42:23 +03:00
< / s e l e c t >
2016-06-23 01:17:22 +03:00
< label > < input type = "checkbox" checked = { this . props . sort . ascending } / > Sort ascending < / l a b e l >
< label > < input type = "checkbox" checked = { this . props . sort . threaded } / > Threaded < / l a b e l >
2016-06-20 01:42:23 +03:00
< / d i v >
}
2016-06-20 23:11:04 +03:00
} ) ;
2016-06-20 01:42:23 +03:00
2016-06-20 23:11:04 +03:00
var ListSortSettingsWindow = React . createClass ( {
2016-06-21 16:57:33 +03:00
mixins : [ DropDownBase ] ,
2016-06-20 01:42:23 +03:00
render : function ( )
{
var sort = this . props . override ? this . props . sorting : this . props . defaultSorting ;
2016-06-21 16:57:33 +03:00
return < div ref = "dd" onClick = { this . onClick } className = { 'dropdown window list-sort' + ( this . state . visible ? ' visible' : '' ) }
id = { 'dropdown-' + this . props . id } tabIndex = "1" style = { { top : this . state . top , left : this . state . left } } >
2016-06-21 18:31:21 +03:00
< div ref = "callout" className = "callout-top" style = { { left : this . state . calloutLeft } } > < / d i v >
2016-06-20 23:11:04 +03:00
< div className = "title" > Sorting for { this . props . folder } < / d i v >
2016-06-20 01:42:23 +03:00
< label > < input type = "checkbox" checked = { this . props . override ? "checked" : null } / > Override default sorting < / l a b e l >
2016-06-20 23:11:04 +03:00
< ListSortSettings className = "sorting" sort = { sort } / >
< div className = "show" >
< a className = "button" onClick = { this . expandChecks } > < span className = { this . state . checksVisible ? 'collapse' : 'expand' } > < / s p a n > S h o w < / a >
2016-06-20 01:42:23 +03:00
< / d i v >
2016-06-20 23:11:04 +03:00
< div className = "show-checks" style = { { display : this . state . checksVisible ? null : 'none' } } >
2016-06-20 01:42:23 +03:00
< label > < input type = "checkbox" checked = { this . props . show . read ? "checked" : null } / > Show Read < / l a b e l >
< label > < input type = "checkbox" checked = { this . props . show . trash ? "checked" : null } / > Show Trash < / l a b e l >
< label > < input type = "checkbox" checked = { this . props . show . spam ? "checked" : null } / > Show Spam < / l a b e l >
< label > < input type = "checkbox" checked = { this . props . show . lists ? "checked" : null } / > Show Mailing Lists < / l a b e l >
< label > < input type = "checkbox" checked = { this . props . show . sent ? "checked" : null } / > Show Sent < / l a b e l >
< label > < input type = "checkbox" checked = { this . props . show . dups ? "checked" : null } / > Show Duplicates < / l a b e l >
< / d i v >
< / d i v >
} ,
getInitialState : function ( )
{
return { checksVisible : false } ;
} ,
expandChecks : function ( )
{
this . setState ( { checksVisible : ! this . state . checksVisible } ) ;
}
} ) ;
2016-06-20 23:11:04 +03:00
var MailSettingsWindow = React . createClass ( {
2016-06-21 16:57:33 +03:00
mixins : [ DropDownBase ] ,
2016-06-20 01:42:23 +03:00
render : function ( )
{
2016-06-21 18:31:21 +03:00
return < div ref = "dd" onClick = { this . onClick } className = { 'dropdown window' + ( this . state . visible ? ' visible' : '' ) }
id = { 'dropdown-' + this . props . id } tabIndex = "1" style = { { top : this . state . top , left : this . state . left } } >
< div ref = "callout" className = "callout-top" style = { { left : this . state . calloutLeft } } > < / d i v >
2016-06-20 23:11:04 +03:00
< div className = "text" > Mail Layout < / d i v >
< div className = "layouts" >
2016-06-22 00:14:07 +03:00
< a onClick = { this . switchLayout } className = { 'button mail-message-on-right' + ( this . state . layout == 'message-on-right' ? ' selected' : '' ) } title = "List and Message on Right" > < span > < / s p a n > < / a >
< a onClick = { this . switchLayout } className = { 'button mail-message-on-bottom' + ( this . state . layout == 'message-on-bottom' ? ' selected' : '' ) } title = "List and Message Below" > < span > < / s p a n > < / a >
< a onClick = { this . switchLayout } className = { 'button mail-message-invisible' + ( this . state . layout == 'message-invisible' ? ' selected' : '' ) } title = "List Only" > < span > < / s p a n > < / a >
2016-06-20 01:42:23 +03:00
< / d i v >
2016-06-20 23:11:04 +03:00
< div className = "split" > < i > < / i > < / d i v >
< div className = "text" > Default List Sorting < / d i v >
< ListSortSettings className = "fields" sort = { this . props . defaultSorting } / >
2016-06-22 00:14:07 +03:00
< div className = "fields" >
< label > < input type = "checkbox" checked = { this . state . showQuickReply } onClick = { this . showQuickReply } / > Show Quick Reply < / l a b e l >
< / d i v >
2016-06-20 23:11:04 +03:00
< div className = "split" > < i > < / i > < / d i v >
< div className = "text" > Mark as Read < / d i v >
< div className = "fields" >
2016-06-21 16:57:33 +03:00
< select className = "sortby" defaultValue = { this . props . markDelay } >
< option value = "-1" > Manually < / o p t i o n >
< option value = "0" > On Select < / o p t i o n >
< option value = "1" > After 1 second < / o p t i o n >
< option value = "3" > After 3 seconds < / o p t i o n >
< option value = "5" > After 5 seconds < / o p t i o n >
2016-06-20 01:42:23 +03:00
< / s e l e c t >
< / d i v >
< / d i v >
} ,
2016-06-22 00:14:07 +03:00
componentDidMount : function ( )
{
2016-06-22 13:37:40 +03:00
Store . on ( 'layout' , this . setLayout ) ;
Store . on ( 'quickReply' , this . setQuickReply ) ;
} ,
componentWillUnmount : function ( )
{
Store . un ( 'layout' , this . setLayout ) ;
Store . un ( 'quickReply' , this . setQuickReply ) ;
2016-06-22 00:14:07 +03:00
} ,
setLayout : function ( )
{
this . setState ( { layout : Store . layout } ) ;
} ,
2016-06-22 13:37:40 +03:00
setQuickReply : function ( )
{
this . setState ( { showQuickReply : Store . quickReply } ) ;
} ,
2016-06-22 00:14:07 +03:00
switchLayout : function ( ev )
{
var t = ev . target . nodeName == 'A' ? ev . target : ev . target . parentNode ;
var l = / mail-(\S+)/ . exec ( t . className ) [ 1 ] ;
2016-06-22 13:37:40 +03:00
Store . set ( 'layout' , l ) ;
2016-06-22 00:14:07 +03:00
} ,
2016-06-20 01:42:23 +03:00
getInitialState : function ( )
{
2016-06-22 13:37:40 +03:00
return { showQuickReply : Store . quickReply , layout : Store . layout } ;
2016-06-20 01:42:23 +03:00
} ,
showQuickReply : function ( )
{
2016-06-22 13:37:40 +03:00
Store . set ( 'quickReply' , ! this . state . showQuickReply ) ;
2016-06-20 01:42:23 +03:00
}
} ) ;
2016-06-20 23:11:04 +03:00
var dropdown _list _sort = React . createElement (
2016-06-20 01:42:23 +03:00
ListSortSettingsWindow , {
2016-06-21 16:57:33 +03:00
id : 'list-sort' ,
window : true ,
2016-06-20 01:42:23 +03:00
folder : 'INBOX' ,
override : false ,
sorting : { } ,
defaultSorting : {
sort : {
sortby : 'sent date' ,
group : 'date' ,
ascending : false ,
threaded : false
}
} ,
show : {
read : true ,
trash : false ,
spam : false ,
lists : true ,
sent : true ,
dups : true
}
}
2016-06-20 23:11:04 +03:00
) ;
2016-06-20 01:42:23 +03:00
2016-06-20 23:11:04 +03:00
var dropdown _settings = React . createElement (
2016-06-20 01:42:23 +03:00
MailSettingsWindow , {
2016-06-21 16:57:33 +03:00
id : 'settings' ,
window : true ,
2016-06-20 01:42:23 +03:00
markDelay : - 1 ,
defaultSorting : {
sort : {
sortby : 'sent date' ,
group : 'date' ,
ascending : false ,
threaded : false
}
}
}
) ;
2016-06-20 23:11:04 +03:00
var AccountFolders = React . createClass ( {
2016-06-20 01:42:23 +03:00
render : function ( )
{
2016-06-20 23:11:04 +03:00
return < div className = "account" >
2016-06-21 22:55:28 +03:00
< div className = { "account-header" + ( this . state . collapsed ? ' collapsed' : '' ) } onClick = { this . onClick } >
2016-06-20 01:42:23 +03:00
{ this . props . name }
2016-06-22 01:01:37 +03:00
< div key = "n" className = "msg-count" > { this . props . unreadCount } < / d i v >
2016-06-20 23:11:04 +03:00
{ this . props . accountId ? [
< div key = "load" className = "loading icon" style = { { display : this . props . loading ? '' : 'none' } } > < / d i v > ,
< div key = "warn" className = "warning icon" style = { { display : this . props . warning ? '' : 'none' } } > < / d i v > ,
2016-06-21 22:55:28 +03:00
< div key = "cfg" className = { 'cfg' + ( this . state . cfgPressed ? ' pressed' : '' ) } onClick = { this . showCfg } > < / d i v >
2016-06-20 23:11:04 +03:00
] : null }
2016-06-20 01:42:23 +03:00
< / d i v >
2016-06-21 22:55:28 +03:00
< div className = { "account-folders" + ( this . state . collapsed ? ' collapsed' : '' ) } style = { { height : this . state . h } } >
< div ref = "vis" className = { 'visible-part' + ( this . state . animating ? ' animating' : '' ) } >
2016-06-20 23:11:04 +03:00
{ this . props . folders . map ( ( f , i ) =>
2016-06-22 14:31:15 +03:00
< div key = { 'f' + i } data - i = { i } className = { 'folder' + ( f . unreadCount > 0 ? ' with-unread' : '' ) +
( this . state . selected == i ? ' selected' : '' ) } onClick = { this . selectFolder } >
2016-06-20 01:42:23 +03:00
{ f . icon ? < img src = { 'icons/' + f . icon + '.png' } / > : null }
2016-06-20 23:11:04 +03:00
{ ' ' }
2016-06-20 01:42:23 +03:00
< span > { f . name } < / s p a n >
2016-06-20 23:11:04 +03:00
{ f . unreadCount > 0 ? < div className = "msg-count" > { f . unreadCount } < / d i v > : n u l l }
2016-06-20 01:42:23 +03:00
< / d i v >
2016-06-20 23:11:04 +03:00
) }
2016-06-21 22:55:28 +03:00
< / d i v >
< / d i v >
2016-06-20 01:42:23 +03:00
< / d i v >
} ,
2016-06-22 14:31:15 +03:00
selectFolder : function ( ev )
{
var t = ev . target ;
while ( t && ! t . getAttribute ( 'data-i' ) && t != this . refs . vis )
t = t . parentNode ;
if ( t && t != this . refs . vis )
{
var i = t . getAttribute ( 'data-i' ) ;
this . setState ( { selected : i } ) ;
this . props . onSelect ( this , i ) ;
}
// FIXME: send select event + switch focus to message list if folder changed
} ,
2016-06-21 22:55:28 +03:00
showCfg : function ( ev )
{
var self = this ;
var i = DropDownBase . instances . account . state . items ;
i [ 0 ] . text = 'Read ' + this . props . name ;
DropDownBase . instances . account . setState ( { items : i } ) ;
DropDownBase . instances . account . showAt ( ev . target , function ( )
{
self . setState ( { cfgPressed : false } ) ;
} ) ;
self . setState ( { cfgPressed : true } ) ;
ev . stopPropagation ( ) ;
} ,
2016-06-20 01:42:23 +03:00
getInitialState : function ( )
{
2016-06-22 14:31:15 +03:00
return { collapsed : this . props . collapsed , animating : false , h : null , cfgPressed : false , selected : - 1 } ;
2016-06-21 22:55:28 +03:00
} ,
onClick : function ( )
{
var self = this ;
if ( this . state . animating )
return ;
this . setState ( { animating : true , h : this . refs . vis . offsetHeight } ) ;
if ( ! this . state . collapsed )
{
setTimeout ( function ( )
{
self . setState ( { h : 0 } ) ;
} , 50 ) ;
}
setTimeout ( function ( )
{
self . setState ( { collapsed : ! self . state . collapsed , animating : false , h : null } ) ;
} , this . state . collapsed ? 200 : 250 ) ;
2016-06-20 01:42:23 +03:00
}
} ) ;
2016-06-20 23:11:04 +03:00
var FolderList = React . createClass ( {
2016-06-20 01:42:23 +03:00
render : function ( )
{
2016-06-22 14:31:15 +03:00
var self = this ;
2016-06-20 23:11:04 +03:00
return < div className = { "folder-list" + ( this . props . progress !== undefined ? ' progress-visible' : '' ) } >
< div className = "top-border-gradient" > < / d i v >
< div className = "bottom-border-gradient" > < / d i v >
< div className = "actions" >
< a className = "button" > < img src = "icons/compose.png" / > Compose < / a >
2016-06-21 16:57:33 +03:00
< DropDownButton dropdownId = "check-send" className = "check-send" icon = "mail_check_send" / >
2016-06-20 01:42:23 +03:00
< / d i v >
2016-06-22 14:31:15 +03:00
// TODO: keyboard navigation
< div className = "listview" tabIndex = "1" >
2016-06-20 01:42:23 +03:00
{ this . props . accounts . map ( function ( account ) {
2016-06-22 14:31:15 +03:00
return < AccountFolders key = { 'a' + account . accountId } onSelect = { self . onSelectFolder } { ... account } / >
2016-06-20 01:42:23 +03:00
} ) }
< / d i v >
2016-06-20 23:11:04 +03:00
< div className = "progress-bar" ref = "pbar" >
< div className = "pending" style = { { width : this . state . pbarWidth } } > Loading database ( { this . props . progress || 0 } % ) < / d i v >
< div className = "clip" style = { { width : ( this . props . progress || 0 ) + '%' , overflow : 'hidden' } } >
< div className = "done" ref = "pdone" style = { { width : this . state . pbarWidth } } > Loading database ( { this . props . progress || 0 } % ) < / d i v >
2016-06-20 01:42:23 +03:00
< / d i v >
< / d i v >
< / d i v >
2016-06-20 23:11:04 +03:00
} ,
2016-06-22 14:31:15 +03:00
onSelectFolder : function ( folders , i )
{
if ( this . prevSelected && this . prevSelected != folders )
this . prevSelected . setState ( { selected : - 1 } ) ;
this . prevSelected = folders ;
} ,
2016-06-20 23:11:04 +03:00
getInitialState : function ( )
{
return { pbarWidth : '' } ;
} ,
onResize : function ( )
{
this . setState ( { pbarWidth : this . refs . pbar . offsetWidth } ) ;
} ,
componentDidMount : function ( )
{
window . addEventListener ( 'resize' , this . onResize ) ;
this . onResize ( ) ;
} ,
componentWillUnmount : function ( )
{
window . removeEventListener ( 'resize' , this . onResize ) ;
2016-06-20 01:42:23 +03:00
}
} ) ;
2016-06-20 23:11:04 +03:00
var TabPanel = React . createClass ( {
2016-06-20 01:42:23 +03:00
render : function ( )
{
var bar = [ ] ;
var body = [ ] ;
2016-06-20 23:11:04 +03:00
for ( var i = 0 ; i < this . state . tabs . length ; i ++ )
2016-06-20 01:42:23 +03:00
{
2016-06-22 00:14:07 +03:00
var t = this . state . tabs [ i ] ;
2016-06-20 01:42:23 +03:00
bar . push (
2016-06-20 23:11:04 +03:00
< div key = { 't' + i } className = { 'tab' + ( i == this . state . selected ? ' selected' : '' ) + ( t . noclose ? ' noclose' : '' ) }
id = { 't-tab' + i } onClick = { this . switchTab } style = { i == this . state . closing ? { width : '1px' , padding : '0' , opacity : '0' } : null } >
{ t . noclose ? null : < a className = "close" onClick = { this . closeTab } > < / a > }
< img src = { 'icons/' + t . icon + '.png' } className = { t . i16 ? 'i16' : null } / > { t . title }
2016-06-20 01:42:23 +03:00
< / d i v >
) ;
body . push (
2016-06-20 23:11:04 +03:00
< div key = { 'c' + i } className = { 'tab-content' + ( t . className ? ' ' + t . className : '' ) }
id = { 'tab' + i } style = { { display : i == this . state . selected ? null : 'none' } } >
{ t . children }
2016-06-20 01:42:23 +03:00
< / d i v >
) ;
}
2016-06-22 00:14:07 +03:00
return < div className = "tab-panel" >
2016-06-20 23:11:04 +03:00
< div className = "tab-bar" > { bar } < / d i v >
2016-06-20 01:42:23 +03:00
{ body }
2016-06-22 00:14:07 +03:00
< / d i v >
} ,
componentWillReceiveProps : function ( nextProps , nextContent )
{
2016-06-22 14:31:15 +03:00
// FIXME: Do not own tabs?
2016-06-22 00:14:07 +03:00
this . setState ( { selected : this . state . selected % nextProps . tabs . length , tabs : nextProps . tabs } ) ;
2016-06-20 01:42:23 +03:00
} ,
getInitialState : function ( )
{
2016-06-22 00:14:07 +03:00
return { selected : 0 , tabs : this . props . tabs } ;
2016-06-20 01:42:23 +03:00
} ,
switchTab : function ( ev )
{
this . setState ( { selected : ev . target . id . substr ( 5 ) } ) ;
} ,
closeTab : function ( ev )
{
var self = this ;
var tab = ev . target . parentNode ;
//this.setState({ closing: tab.id.substr(5) });
tab . style . width = '1px' ;
tab . style . padding = '0' ;
tab . style . opacity = '0' ;
setTimeout ( function ( )
{
var t = self . state . tabs ;
t . splice ( tab . id . substr ( 5 ) , 1 ) ;
var s = self . state . selected ;
if ( 't-tab' + s == tab . id )
s = self . state . selected - 1 ;
this . setState ( { tabs : t , selected : s } ) ;
} , 200 ) ;
ev . stopPropagation ( ) ;
}
} ) ;
2016-06-20 20:15:06 +03:00
function formatBytes ( s )
{
2016-06-21 22:55:28 +03:00
if ( ! s ) return '' ;
2016-06-20 20:15:06 +03:00
if ( s < 1024 ) return s + ' B' ;
else if ( s < 1024 * 1024 ) return ( Math . round ( s * 10 / 1024 ) / 10 ) + ' KB' ;
else if ( s < 1024 * 1024 * 1024 ) return ( Math . round ( s * 10 / 1024 / 1024 ) / 10 ) + ' MB' ;
return ( Math . round ( s * 10 / 1024 / 1024 / 1024 ) / 10 ) + ' GB' ;
}
function formatDate ( dt )
{
2016-06-21 22:55:28 +03:00
if ( ! ( dt instanceof Date ) )
2016-06-22 13:37:40 +03:00
dt = new Date ( dt . replace ( ' ' , 'T' ) ) ;
2016-06-20 20:15:06 +03:00
var tod = new Date ( ) ;
tod . setHours ( 0 ) ;
tod . setMinutes ( 0 ) ;
tod . setSeconds ( 0 ) ;
tod . setMilliseconds ( 0 ) ;
var prevweek = tod ;
prevweek = prevweek . getTime ( ) - ( 7 + ( prevweek . getDay ( ) + 6 ) % 7 ) * 86400000 ;
if ( dt . getTime ( ) < prevweek )
2016-06-20 01:42:23 +03:00
{
2016-06-20 20:15:06 +03:00
var d = dt . getDate ( ) ;
var m = dt . getMonth ( ) + 1 ;
2016-06-28 14:17:20 +03:00
return ( d < 10 ? '0' : '' ) + d + ' ' + ( m < 10 ? '0' : '' ) + m + ' ' + dt . getFullYear ( ) ;
2016-06-20 20:15:06 +03:00
}
else if ( dt . getTime ( ) < tod . getTime ( ) )
{
2016-06-22 13:37:40 +03:00
return WeekDays [ dt . getDay ( ) ] + ' ' + dt . getDate ( ) + ' ' + Months [ dt . getMonth ( ) ] ;
2016-06-20 20:15:06 +03:00
}
2016-06-21 22:55:28 +03:00
var h = dt . getHours ( ) ;
var m = dt . getMinutes ( ) ;
2016-06-20 20:15:06 +03:00
return ( h < 10 ? '0' : '' ) + h + ':' + ( m < 10 ? '0' : '' ) + m ;
}
2016-06-23 17:27:12 +03:00
// Common selection mixin
var ListWithSelection = {
// requires to override methods: this.deleteSelected(), this.getPageSize(), this.getItemOffset(index), this.getTotalItems()
2016-06-20 01:42:23 +03:00
getInitialState : function ( )
{
return {
2016-06-23 17:27:12 +03:00
selected : { }
2016-06-20 01:42:23 +03:00
} ;
} ,
2016-06-23 17:50:23 +03:00
isSelected : function ( i )
{
return this . state . selected [ i ] || this . state . selected . begin !== undefined &&
this . state . selected . begin <= i && this . state . selected . end >= i ;
} ,
2016-06-23 17:27:12 +03:00
onListKeyDown : function ( ev )
2016-06-20 01:42:23 +03:00
{
2016-06-23 17:27:12 +03:00
if ( ! this . getTotalItems ( ) )
2016-06-22 21:23:50 +03:00
return ;
2016-06-22 16:16:57 +03:00
if ( ev . keyCode == 46 ) // delete
{
2016-06-23 17:27:12 +03:00
this . deleteSelected ( ) ;
this . setState ( { selected : { } } ) ;
2016-06-22 16:16:57 +03:00
ev . stopPropagation ( ) ;
}
2016-06-22 21:23:50 +03:00
else if ( ev . keyCode == 38 || ev . keyCode == 40 || ev . keyCode == 33 || ev . keyCode == 34 ) // up, down, pgup, pgdown
2016-06-22 16:16:57 +03:00
{
2016-06-22 21:23:50 +03:00
var sel = this . curSel , dir ;
if ( ev . keyCode < 35 )
2016-06-23 17:27:12 +03:00
dir = ( ev . keyCode == 34 ? 1 : - 1 ) * this . getPageSize ( ) ;
2016-06-22 21:23:50 +03:00
else
dir = ( ev . keyCode == 40 ? 1 : - 1 ) ;
if ( sel !== null )
2016-06-22 16:16:57 +03:00
{
2016-06-23 22:36:21 +03:00
var nsel = sel + dir , n = this . getTotalItems ( ) ;
2016-06-22 21:23:50 +03:00
if ( nsel < 0 )
nsel = 0 ;
2016-06-23 22:36:21 +03:00
if ( nsel >= n )
nsel = n - 1 ;
2016-06-22 21:23:50 +03:00
if ( sel != nsel )
2016-06-22 16:16:57 +03:00
{
2016-06-22 21:23:50 +03:00
if ( ev . shiftKey )
this . selectTo ( nsel ) ;
else
this . selectOne ( nsel ) ;
2016-06-23 17:27:12 +03:00
var pos = this . getItemOffset ( nsel ) ;
if ( pos [ 0 ] + pos [ 1 ] > this . refs . scroll . scrollTop + this . refs . scroll . offsetHeight )
this . refs . scroll . scrollTop = pos [ 0 ] + pos [ 1 ] - this . refs . scroll . offsetHeight ;
else if ( pos [ 0 ] < this . refs . scroll . scrollTop + this . getScrollPaddingTop ( ) )
this . refs . scroll . scrollTop = pos [ 0 ] - this . getScrollPaddingTop ( ) ;
2016-06-22 21:23:50 +03:00
ev . stopPropagation ( ) ;
2016-06-22 16:16:57 +03:00
}
2016-06-23 17:27:12 +03:00
ev . preventDefault ( ) ; // prevent scroll
2016-06-22 16:16:57 +03:00
}
2016-06-22 21:23:50 +03:00
}
else if ( ev . keyCode == 36 ) // home
{
if ( ev . shiftKey )
2016-06-23 17:27:12 +03:00
{
2016-06-22 21:23:50 +03:00
this . selectTo ( 0 ) ;
2016-06-23 17:27:12 +03:00
this . refs . scroll . scrollTop = pos [ 0 ] - this . getScrollPaddingTop ( ) ;
}
2016-06-22 21:23:50 +03:00
else
this . selectOne ( 0 ) ;
}
else if ( ev . keyCode == 35 ) // end
{
2016-06-23 17:27:12 +03:00
var nsel = this . getTotalItems ( ) - 1 ;
2016-06-22 21:23:50 +03:00
if ( ev . shiftKey )
2016-06-23 17:27:12 +03:00
{
this . selectTo ( nsel ) ;
var pos = this . getItemOffset ( nsel ) ;
this . refs . scroll . scrollTop = pos [ 0 ] + pos [ 1 ] - this . refs . scroll . offsetHeight ;
}
2016-06-22 21:23:50 +03:00
else
2016-06-23 17:27:12 +03:00
this . selectOne ( nsel ) ;
2016-06-22 16:16:57 +03:00
}
} ,
2016-06-22 21:23:50 +03:00
selectTo : function ( ns )
{
if ( this . lastSel === undefined )
return this . selectOne ( ns ) ;
2016-06-23 17:50:23 +03:00
var sel = { } ;
2016-06-23 22:36:21 +03:00
var n = this . getTotalItems ( ) ;
if ( this . lastSel >= n )
this . lastSel = n - 1 ;
2016-06-22 21:23:50 +03:00
if ( ns < this . lastSel )
2016-06-23 17:50:23 +03:00
sel = { begin : ns , end : this . lastSel } ;
2016-06-22 21:23:50 +03:00
else if ( ns > this . lastSel )
2016-06-23 17:50:23 +03:00
sel = { begin : this . lastSel , end : ns } ;
else
sel [ ns ] = true ;
2016-06-23 17:27:12 +03:00
this . setState ( { selected : sel } ) ;
2016-06-22 21:23:50 +03:00
this . curSel = ns ;
2016-06-23 23:31:20 +03:00
if ( this . onSelectCurrent )
this . onSelectCurrent ( ns ) ;
2016-06-22 21:23:50 +03:00
} ,
selectOne : function ( ns )
{
2016-06-23 17:27:12 +03:00
var sel = { } ;
sel [ ns ] = true ;
this . setState ( { selected : sel } ) ;
2016-06-22 21:23:50 +03:00
this . lastSel = ns ;
this . curSel = ns ;
2016-06-23 23:31:20 +03:00
if ( this . onSelectCurrent )
this . onSelectCurrent ( ns ) ;
2016-06-22 21:23:50 +03:00
} ,
2016-06-23 17:27:12 +03:00
onListItemClick : function ( ev )
2016-06-22 16:16:57 +03:00
{
var t = ev . target ;
while ( t && ! t . getAttribute ( 'data-i' ) )
t = t . parentNode ;
if ( t )
{
var ns = parseInt ( t . getAttribute ( 'data-i' ) ) ;
2016-06-22 21:23:50 +03:00
if ( ev . shiftKey )
this . selectTo ( ns ) ;
2016-06-22 16:16:57 +03:00
else if ( ev . ctrlKey )
{
2016-06-23 17:27:12 +03:00
this . state . selected [ ns ] = true ;
2016-06-22 21:23:50 +03:00
this . curSel = ns ;
2016-06-23 23:31:20 +03:00
if ( this . onSelectCurrent )
this . onSelectCurrent ( ns ) ;
2016-06-22 21:23:50 +03:00
this . lastSel = this . lastSel === undefined ? ns : this . lastSel ;
2016-06-23 17:27:12 +03:00
this . setState ( { selected : this . state . selected } ) ;
2016-06-22 16:16:57 +03:00
}
else
2016-06-22 21:23:50 +03:00
this . selectOne ( ns ) ;
2016-06-22 16:16:57 +03:00
}
2016-06-23 17:27:12 +03:00
}
} ;
var AttachList = React . createClass ( {
mixins : [ ListWithSelection ] ,
getInitialState : function ( )
{
return {
attachments : [ ] ,
attachScroll : 0
} ;
} ,
addAttachments : function ( ev )
{
var a = this . state . attachments ;
if ( ev . target . files )
for ( var i = 0 ; i < ev . target . files . length ; i ++ )
a . push ( ev . target . files [ i ] ) ;
this . setState ( { attachments : a } ) ;
// reset file input
ev . target . innerHTML = ev . target . innerHTML ;
} ,
scrollAttachList : function ( ev )
{
this . setState ( { attachScroll : ev . target . scrollTop } ) ;
} ,
deleteSelected : function ( )
{
for ( var i = this . state . attachments . length - 1 ; i >= 0 ; i -- )
if ( this . state . selected [ i ] )
this . state . attachments . splice ( i , 1 ) ;
this . setState ( { attachments : this . state . attachments } ) ;
} ,
getTotalItems : function ( )
{
return this . state . attachments . length ;
} ,
getPageSize : function ( )
{
return this . refs . a0 ? Math . round ( this . refs . scroll . offsetHeight / this . refs . a0 . offsetHeight ) : 1 ;
} ,
getItemOffset : function ( index )
{
var item = this . refs [ 'a' + index ] ;
return [ item . offsetTop , item . offsetHeight ] ;
} ,
getScrollPaddingTop : function ( )
{
return this . refs . title . offsetHeight ;
2016-06-22 16:16:57 +03:00
} ,
2016-06-20 01:42:23 +03:00
render : function ( )
2016-06-22 22:12:52 +03:00
{
return < div className = "attach" >
< div className = "no-attach" style = { this . state . attachments . length ? { display : 'none' } : null } >
< input type = "file" multiple = "multiple" onChange = { this . addAttachments } / >
< / d i v >
2016-06-23 17:27:12 +03:00
< div ref = "scroll" className = "attach-list" tabIndex = "1" onScroll = { this . scrollAttachList } onKeyDown = { this . onListKeyDown }
2016-06-22 22:12:52 +03:00
style = { this . state . attachments . length ? null : { display : 'none' } } >
< div ref = "title" className = "title" style = { { top : this . state . attachScroll } } >
< div className = "name" > Attachment < a className = "button" >
< img src = "icons/attach.png" / >
< input type = "file" multiple = "multiple" onChange = { this . addAttachments } / >
< / a > < / d i v >
< div className = "size" > Size < / d i v >
< / d i v >
{ this . state . attachments . map ( ( a , i ) =>
< div ref = { 'a' + i } title = { a . name + ' (' + formatBytes ( a . size ) + ')' } key = { 'a' + i } data - i = { i }
2016-06-23 17:50:23 +03:00
className = { 'attachment' + ( this . isSelected ( i ) ? ' selected' : '' ) } onMouseDown = { this . onListItemClick } >
2016-06-22 22:12:52 +03:00
< div className = "name" > { a . name } < / d i v >
< div className = "size" > { formatBytes ( a . size ) } < / d i v >
< / d i v >
) }
< / d i v >
< / d i v >
}
} ) ;
var ComposeWindow = React . createClass ( {
getInitialState : function ( )
{
return {
text : ''
} ;
} ,
changeText : function ( ev )
{
this . setState ( { text : ev . target . value } ) ;
} ,
render : function ( )
2016-06-20 01:42:23 +03:00
{
2016-06-20 23:11:04 +03:00
return < div className = "compose" >
< div className = "actions" >
< a className = "button" > < img src = "icons/mail_send.png" / > Send < / a >
< a className = "button" > < img src = "icons/delete.png" / > < / a >
2016-06-20 01:42:23 +03:00
< / d i v >
2016-06-20 23:11:04 +03:00
< div className = "flex" >
< div className = "headers" >
< div className = "headers-table" >
< div className = "header" >
< div className = "field" > From < / d i v >
< div className = "value" >
2016-06-20 01:42:23 +03:00
< select >
2016-06-20 23:11:04 +03:00
{ this . props . accounts . map ( ( a , i ) =>
< option key = { 'a' + i } > { '"' + a . name + '" <' + a . email + '>' } < / o p t i o n >
) }
2016-06-20 01:42:23 +03:00
< / s e l e c t >
< / d i v >
< / d i v >
2016-06-20 23:11:04 +03:00
< div className = "header" >
< div className = "field" > To < / d i v >
< div className = "value" > < input / > < / d i v >
2016-06-20 01:42:23 +03:00
< / d i v >
2016-06-20 23:11:04 +03:00
< div className = "header" >
< div className = "field" > Cc < / d i v >
< div className = "value" > < input / > < / d i v >
2016-06-20 01:42:23 +03:00
< / d i v >
2016-06-20 23:11:04 +03:00
< div className = "header" >
< div className = "field" > Bcc < / d i v >
< div className = "value" > < input / > < / d i v >
2016-06-20 01:42:23 +03:00
< / d i v >
2016-06-20 23:11:04 +03:00
< div className = "header" >
< div className = "field" > Subject < / d i v >
< div className = "value" > < input / > < / d i v >
2016-06-20 01:42:23 +03:00
< / d i v >
< / d i v >
2016-06-22 22:12:52 +03:00
< AttachList / >
2016-06-20 01:42:23 +03:00
< / d i v >
2016-06-20 23:11:04 +03:00
< div className = "text" >
< textarea onChange = { this . changeText } defaultValue = { this . state . text } > < / t e x t a r e a >
2016-06-20 01:42:23 +03:00
< / d i v >
< / d i v >
< / d i v >
}
} ) ;
2016-06-20 23:11:04 +03:00
var MessageInList = React . createClass ( {
2016-06-22 14:31:15 +03:00
msgClasses : [ 'unread' , 'unseen' , 'replied' , 'pinned' , 'sent' , 'unloaded' ] ,
2016-06-20 20:15:06 +03:00
render : function ( )
{
var msg = this . props . msg ;
2016-06-23 22:36:21 +03:00
return < div data - i = { this . props . i } className = { 'message' + ( this . msgClasses . map ( c => ( msg [ c ] ? ' ' + c : '' ) ) . join ( '' ) ) +
2016-06-23 23:31:20 +03:00
( this . props . selected ? ' selected' : '' ) + ( msg . thread && Store . threads ? ' thread0' : '' ) } onMouseDown = { this . props . onClick } >
2016-06-22 00:14:07 +03:00
< div className = "icon" style = { { width : ( 20 + 10 * ( msg . level || 0 ) ) , backgroundPosition : ( 10 * ( msg . level || 0 ) ) + 'px 7px' } } > < / d i v >
2016-06-22 00:50:07 +03:00
< div className = "subject" style = { { paddingLeft : ( 20 + 10 * ( msg . level || 0 ) ) } } > { msg . subject } < / d i v >
2016-06-23 01:17:22 +03:00
{ msg . thread && Store . threads ? < div className = { 'expand' + ( msg . collapsed ? '' : ' collapse' ) } > < / d i v > : n u l l }
2016-06-20 23:11:04 +03:00
< div className = "bullet" > < / d i v >
2016-06-22 00:14:07 +03:00
< div className = "from" style = { { left : ( 21 + 10 * ( msg . level || 0 ) ) } } > { ( msg . sent || msg . outgoing ? 'To ' + msg . to : msg . from ) } < / d i v >
2016-06-20 23:11:04 +03:00
< div className = "size" > { formatBytes ( msg . size ) } < / d i v >
< div className = "attach" style = { msg . attach ? null : { display : 'none' } } > < / d i v >
2016-06-22 13:37:40 +03:00
< div className = "time" > { formatDate ( msg . time ) } < / d i v >
2016-06-20 20:15:06 +03:00
< / d i v >
}
} ) ;
2016-07-06 18:50:12 +03:00
// TODO: expand/collapse days
2016-06-20 23:11:04 +03:00
var MessageList = React . createClass ( {
2016-06-23 22:36:21 +03:00
mixins : [ ListWithSelection ] ,
2016-06-20 23:11:04 +03:00
getInitialState : function ( )
{
2016-06-24 00:37:16 +03:00
return { firstDayTop : 0 , firstDay : this . props . groups [ 0 ] . name , groups : this . props . groups /*FIXME*/ } ;
2016-06-20 23:11:04 +03:00
} ,
2016-06-20 01:42:23 +03:00
changeFirstDay : function ( ev )
{
2016-06-24 00:37:16 +03:00
var scrollTop = ev . target . scrollTop , scrollSize = ev . target . offsetHeight - this . getScrollPaddingTop ( ) ;
var top = 0 , p , firstVisibleGrp , firstVisible , lastVisibleGrp , lastVisible ;
var itemH = ( Store . layout == 'message-on-right' ? 60 : 30 ) ;
var i ;
for ( i = 0 ; i < this . state . groups . length ; i ++ )
{
p = top ;
top += ( i > 0 ? 30 : 0 ) + itemH * this . state . groups [ i ] . messageCount ;
if ( firstVisibleGrp === undefined && scrollTop < top )
{
firstVisibleGrp = i ;
if ( i > 0 && scrollTop < p + 30 )
firstVisible = 0 ;
else
2016-06-24 15:43:44 +03:00
firstVisible = Math . floor ( ( scrollTop - p - ( i > 0 ? 30 : 0 ) ) / itemH ) ;
2016-06-24 00:37:16 +03:00
}
if ( lastVisibleGrp === undefined && scrollTop + scrollSize < top )
{
lastVisibleGrp = i ;
2016-06-24 15:43:44 +03:00
if ( i > 0 && scrollTop + scrollSize < p + 30 )
2016-06-24 00:37:16 +03:00
lastVisible = 0 ;
else
2016-06-24 15:43:44 +03:00
lastVisible = Math . floor ( ( scrollTop + scrollSize - p - ( i > 0 ? 30 : 0 ) ) / itemH ) ;
if ( lastVisible >= this . state . groups [ i ] . messageCount )
lastVisible = this . state . groups [ i ] . messageCount - 1 ;
2016-06-24 00:37:16 +03:00
}
if ( firstVisibleGrp !== undefined && lastVisibleGrp !== undefined )
break ;
}
2016-06-24 15:43:44 +03:00
if ( lastVisibleGrp === undefined )
{
lastVisibleGrp = this . state . groups . length - 1 ;
lastVisible = this . state . groups [ lastVisibleGrp ] . messageCount - 1 ;
}
this . setState ( {
firstDayTop : scrollTop ,
firstDay : this . state . groups [ firstVisibleGrp ] . name ,
firstGrp : firstVisibleGrp ,
firstMsg : firstVisible ,
lastGrp : lastVisibleGrp ,
lastMsg : lastVisible
} ) ;
2016-06-20 01:42:23 +03:00
} ,
2016-06-23 22:36:21 +03:00
deleteSelected : function ( )
{
2016-06-23 23:31:20 +03:00
} ,
onSelectCurrent : function ( index )
{
var total = 0 , p ;
for ( var i = 0 ; i < this . state . groups . length ; i ++ )
{
p = total ;
2016-06-24 00:37:16 +03:00
total += ( i > 0 ? 1 : 0 ) + this . state . groups [ i ] . messageCount ;
2016-06-23 23:31:20 +03:00
if ( index < total )
{
Store . set ( 'msg' , this . state . groups [ i ] . messages [ index - p - ( i > 0 ? 1 : 0 ) ] ) ;
break ;
}
}
2016-06-23 22:36:21 +03:00
} ,
getTotalItems : function ( )
{
2016-06-23 23:31:20 +03:00
var total = - 1 ; // do not count first-day as item
2016-06-23 22:36:21 +03:00
for ( var i = 0 ; i < this . state . groups . length ; i ++ )
{
2016-06-24 00:37:16 +03:00
total += 1 + this . state . groups [ i ] . messageCount ;
2016-06-23 22:36:21 +03:00
}
return total ;
} ,
getPageSize : function ( )
{
return Math . round ( this . refs . scroll . offsetHeight / ( Store . layout == 'message-on-right' ? 60 : 30 ) ) ;
} ,
getItemOffset : function ( index )
{
/ * v a r c , g m i n = 0 , g m a x = t h i s . s t a t e . g r o u p s . l e n g t h ;
while ( gmin != gmax - 1 )
{
c = Math . floor ( ( gmax + gmin ) / 2 ) ;
if ( this . state . groups [ c ]
} * /
2016-06-24 23:45:10 +03:00
var n = 0 , top = this . refs . title . offsetHeight , p ;
2016-06-23 22:36:21 +03:00
for ( var i = 0 ; i < this . state . groups . length ; i ++ )
{
p = n ;
2016-06-24 00:37:16 +03:00
n += ( i > 0 ? 1 : 0 ) + this . state . groups [ i ] . messageCount ;
2016-06-23 22:36:21 +03:00
if ( index < n )
{
if ( index > p )
2016-06-23 23:31:20 +03:00
top += ( i > 0 ? 30 : 0 ) + ( Store . layout == 'message-on-right' ? 60 : 30 ) * ( index - p - 1 ) ;
2016-06-23 22:36:21 +03:00
break ;
}
2016-06-24 00:37:16 +03:00
top += ( i > 0 ? 30 : 0 ) + ( Store . layout == 'message-on-right' ? 60 : 30 ) * this . state . groups [ i ] . messageCount ;
2016-06-23 22:36:21 +03:00
}
2016-06-23 23:31:20 +03:00
return [ top , ( Store . layout == 'message-on-right' && ( index == 0 || index != p ) ? 60 : 30 ) ] ;
2016-06-23 22:36:21 +03:00
} ,
getScrollPaddingTop : function ( )
{
return this . refs . title . offsetHeight ;
} ,
2016-06-24 15:43:44 +03:00
getMessages : function ( grp , start , end )
{
var a = grp . messages . slice ( start , end ) ;
for ( var i = 0 ; i < end - start ; i ++ )
if ( ! a [ i ] )
a [ i ] = null ;
return a ;
} ,
2016-06-20 01:42:23 +03:00
render : function ( )
{
2016-06-23 22:36:21 +03:00
var self = this ;
var total = 0 ;
2016-06-24 15:43:44 +03:00
var itemH = ( Store . layout == 'message-on-right' ? 60 : 30 ) ;
2016-06-20 23:11:04 +03:00
return < div className = "message-list" >
< div className = "top-border-gradient" > < / d i v >
< div className = "bottom-border-gradient" > < / d i v >
< div className = "actions" >
< div className = "searchbox" >
2016-06-20 20:15:06 +03:00
< input type = "text" placeholder = "Search mail" / >
2016-06-20 01:42:23 +03:00
< / d i v >
2016-06-21 16:57:33 +03:00
< DropDownButton dropdownId = "threads" className = "threads"
2016-06-21 21:47:41 +03:00
title = "Show Message Thread" checkedTitle = "Hide Message Thread" icon = "thread" checkedIcon = "thread_selected" checkable = "1" / >
2016-06-22 00:50:07 +03:00
< DropDownButton ref = "setBtn" dropdownId = "settings" className = "settings" whole = "1"
2016-06-21 18:31:21 +03:00
title = "Settings for this folder" icon = "config" / >
2016-06-21 16:57:33 +03:00
< DropDownButton dropdownId = "list-sort" className = "list-sort" whole = "1"
title = "Sorting settings" icon = "list_sort" / >
2016-06-20 23:11:04 +03:00
< div className = "clear" > < / d i v >
2016-06-20 20:15:06 +03:00
< / d i v >
2016-06-23 22:36:21 +03:00
< div ref = "scroll" className = "listview" tabIndex = "1" onScroll = { this . changeFirstDay } onKeyDown = { this . onListKeyDown } >
2016-06-24 00:37:16 +03:00
< div ref = "title" className = "day first-day" style = { { top : this . state . firstDayTop } } > { this . state . firstDay } < / d i v >
2016-06-23 22:36:21 +03:00
{ this . props . groups . map ( function ( grp , i ) {
2016-06-23 23:31:20 +03:00
if ( i > 0 )
total ++ ;
2016-06-24 15:43:44 +03:00
var start = total + ( self . state . firstGrp == i ? self . state . firstMsg : 0 ) ;
2016-06-23 22:36:21 +03:00
var r = [
i > 0 ? < div className = "day" data - i = { total - 1 } > { grp . name } < / d i v > : n u l l ,
< div className = "day-list" >
2016-06-24 15:43:44 +03:00
{ ( self . state . firstGrp > i || self . state . lastGrp < i
? < div className = "placeholder" style = { { height : itemH * grp . messageCount } } > < / d i v >
: [
( self . state . firstGrp == i
? < div className = "placeholder" style = { { height : itemH * self . state . firstMsg } } > < / d i v >
: null ) ,
self . getMessages ( grp ,
self . state . firstGrp == i ? self . state . firstMsg : 0 ,
self . state . lastGrp == i ? self . state . lastMsg + 1 : grp . messageCount
) . map ( ( msg , j ) => ( msg
? [
< MessageInList msg = { msg } i = { start + j } selected = { self . isSelected ( start + j ) } onClick = { self . onListItemClick } / > ,
/ * ( m s g . t h r e a d & & S t o r e . t h r e a d s ?
< div className = "thread" >
{ msg . thread . map ( reply => < MessageInList msg = { reply } i = { 0 } onClick = { self . onListItemClick } / > ) }
< / d i v >
: null ) * /
]
: < div data - i = { start + j } className = { 'message' + ( self . isSelected ( start + j ) ? ' selected' : '' ) } onMouseDown = { self . onListItemClick } > < / d i v >
) ) ,
( self . state . lastGrp == i
? < div className = "placeholder" style = { { height : itemH * ( grp . messageCount - self . state . lastMsg - 1 ) } } > < / d i v >
: null )
]
) }
2016-06-23 22:36:21 +03:00
< / d i v >
] ;
2016-06-24 15:43:44 +03:00
total += grp . messageCount ;
2016-06-23 22:36:21 +03:00
return r ;
} ) }
2016-06-20 01:42:23 +03:00
< / d i v >
< / d i v >
2016-06-20 20:15:06 +03:00
}
} ) ;
2016-06-20 23:11:04 +03:00
var MessageView = React . createClass ( {
2016-06-22 13:37:40 +03:00
formatLongDate : function ( dt )
{
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 ( )
2016-06-20 20:15:06 +03:00
{
2016-06-22 13:37:40 +03:00
this . setState ( { msg : Store . msg } ) ;
} ,
getInitialState : function ( )
{
return { quickReply : Store . quickReply } ;
2016-06-20 20:15:06 +03:00
} ,
render : function ( )
{
2016-06-22 13:37:40 +03:00
var msg = this . state . msg ;
2016-06-22 16:16:57 +03:00
return < div className = { 'message-view' + ( ! msg ? ' no-mail-shown' : '' ) + ( ! this . state . quickReply ? ' no-quick' : '' ) } >
2016-06-20 23:11:04 +03:00
< div className = "actions" >
2016-06-21 18:31:21 +03:00
< DropDownButton dropdownId = "reply" icon = "mail_reply" text = "Reply" / >
2016-06-20 23:11:04 +03:00
< a className = "button" > < img src = "icons/mail_reply_all.png" / > Reply All < / a >
2016-06-21 18:31:21 +03:00
< DropDownButton dropdownId = "forward" icon = "mail_forward" text = "Forward" / >
2016-06-21 21:47:41 +03:00
< 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" / >
2016-06-20 23:11:04 +03:00
< a className = "button show-dropdown" > < img src = "icons/label.png" / > Label < span className = "down" > < / s p a n > < / a >
2016-06-22 00:50:07 +03:00
< DropDownButton ref = "setBtn" dropdownId = "settings" whole = "1" icon = "config" text = "Settings" / >
2016-06-20 20:15:06 +03:00
< / d i v >
2016-06-20 23:11:04 +03:00
< div className = "nomail" >
2016-06-21 16:57:33 +03:00
< div className = "flex1" > < / d i v >
< div className = "middle" >
< img src = "icons/no_mail.png" / >
< div className = "txt" > No message selected < / d i v >
2016-06-20 20:15:06 +03:00
< / d i v >
2016-06-21 16:57:33 +03:00
< div className = "flex1" > < / d i v >
2016-06-20 01:42:23 +03:00
< / d i v >
2016-06-20 23:11:04 +03:00
{ msg ? [
< div className = "headers" >
< div className = "top" >
< div className = "pin" > < / d i v >
2016-06-22 13:37:40 +03:00
< div className = "time" > { this . formatLongDate ( msg . time ) } < / d i v >
2016-06-20 23:11:04 +03:00
< div className = "subject" > { msg . subject } < / d i v >
2016-06-20 20:15:06 +03:00
< / d i v >
2016-06-20 23:11:04 +03:00
< div className = "header-table" >
< div className = "header" >
< div className = "field" > From < / d i v >
2016-06-22 14:31:15 +03:00
< div className = "value" > < a className = "button" > { msg . from + ' <' + msg . fromEmail + '>' } < / a > < / d i v >
2016-06-20 20:15:06 +03:00
< / d i v >
2016-06-20 23:11:04 +03:00
< div className = "header" >
< div className = "field" > To < / d i v >
< div className = "value" > < a className = "button" > { msg . to } < / a > < / d i v >
2016-06-20 20:15:06 +03:00
< / d i v >
{ msg . cc ?
2016-06-20 23:11:04 +03:00
< div className = "header" >
< div className = "field" > Cc < / d i v >
< div className = "value" >
{ msg . cc . map ( cc => < a className = "button" > { cc } < / a > ) }
2016-06-20 20:15:06 +03:00
< / d i v >
< / d i v >
: null }
{ msg . replyto ?
2016-06-20 23:11:04 +03:00
< div className = "header" >
< div className = "field" > Reply - to < / d i v >
< div className = "value" > < a className = "button" > { msg . replyto } < / a > < / d i v >
2016-06-20 20:15:06 +03:00
< / d i v >
: null }
< / d i v >
2016-06-20 23:11:04 +03:00
< / d i v > ,
( msg . blockedImages ?
< div className = "blocked-images" >
2016-06-20 20:15:06 +03:00
< img src = "icons/block.png" / > This message contains blocked images .
2016-06-20 23:11:04 +03:00
< a className = "button raised" > Load Images < / a >
2016-06-20 20:15:06 +03:00
< label > < input type = "checkbox" / > Always load from { msg . from } < / l a b e l >
< / d i v >
2016-06-20 23:11:04 +03:00
: null ) ,
2016-06-22 13:37:40 +03:00
< div className = "text" dangerouslySetInnerHTML = { { _ _html : msg . body } } > < / d i v > ,
this . state . quickReply ?
2016-06-20 23:11:04 +03:00
< div className = "quick-reply" >
2016-06-20 20:15:06 +03:00
< textarea > < / t e x t a r e a >
2016-06-20 23:11:04 +03:00
< 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 >
2016-06-20 20:15:06 +03:00
< / d i v >
2016-06-20 01:42:23 +03:00
< / d i v >
2016-06-22 13:37:40 +03:00
: null
2016-06-20 23:11:04 +03:00
] : null }
2016-06-20 01:42:23 +03:00
< / d i v >
}
} ) ;
2016-06-20 23:11:04 +03:00
var accounts = [
2016-06-20 01:42:23 +03:00
{
2016-06-20 23:11:04 +03:00
name : 'All Messages' ,
accountId : null ,
unreadCount : 65 ,
folders : [
{ name : 'Unread' , icon : 'mail_unread' , unreadCount : 65 } ,
{ name : 'Received' , icon : 'mail_received' , unreadCount : 65 } ,
{ name : 'Pinned' , icon : 'mail_pinned' } ,
{ name : 'Outbox' , icon : 'mail_outbox' } ,
{ name : 'Sent' , icon : 'mail_sent' } ,
{ name : 'Drafts' , icon : 'mail_drafts' , unreadCount : 507 } ,
{ name : 'Spam' , icon : 'mail_spam' } ,
{ name : 'Trash' , icon : 'mail_trash' , unreadCount : 423 } ,
] ,
} ,
2016-06-20 01:42:23 +03:00
{
2016-06-20 23:11:04 +03:00
name : 'vitalif@mail.ru' ,
accountId : 1 ,
unreadCount : 48 ,
warning : true ,
folders : [
{ name : 'Unread' , icon : 'mail_unread' , unreadCount : 48 } ,
{ name : 'INBOX' , icon : 'folder' , unreadCount : 48 } ,
{ name : 'TODO' , icon : 'folder' } ,
{ name : 'Архив' , icon : 'folder' } ,
{ name : 'Корзина' , icon : 'mail_trash' } ,
{ name : 'Отправленные' , icon : 'mail_sent' } ,
{ name : 'Спам' , icon : 'mail_spam' } ,
{ name : 'Черновики' , icon : 'mail_drafts' } ,
{ name : 'Pinned' , icon : 'mail_pinned' } ,
] ,
} ,
2016-06-20 01:42:23 +03:00
{
2016-06-20 23:11:04 +03:00
name : 'vitalif@yourcmc.ru' ,
accountId : 2 ,
unreadCount : 16 ,
loading : true ,
folders : [
{ name : 'Unread' , icon : 'mail_unread' , unreadCount : 16 } ,
{ name : 'Drafts' , icon : 'mail_drafts' } ,
{ name : 'HAM' , icon : 'folder' } ,
{ name : 'INBOX' , icon : 'folder' , unreadCount : 16 } ,
{ name : 'intermedia_su' , icon : 'folder' } ,
{ name : 'Sent' , icon : 'mail_sent' } ,
{ name : 'SPAM' , icon : 'mail_spam' } ,
{ name : 'TRASH' , icon : 'mail_trash' } ,
{ name : 'Pinned' , icon : 'mail_pinned' } ,
] ,
2016-06-20 01:42:23 +03:00
}
2016-06-20 23:11:04 +03:00
] ;
2016-06-20 01:42:23 +03:00
2016-06-20 23:11:04 +03:00
var composeAccounts = [
{ name : 'Виталий Филиппов' , email : 'vitalif@mail.ru' } ,
{ name : 'Vitaliy Filippov' , email : 'vitalif@yourcmc.ru' }
] ;
2016-06-20 01:42:23 +03:00
2016-06-24 15:43:44 +03:00
var msg2 = [ ] ;
msg2 [ 5 ] = {
subject : 'кошку хочешь?))' ,
sent : true ,
from : 'Виталий Филиппов' ,
fromEmail : 'vitalif@mail.ru' ,
to : 'Margarita Philippova' ,
time : '2016-06-14 21:24' ,
body : 'к нам тут пришла какая-то и к нам в дом рвётся, симпатишная) потеряшка какая-то, но явно домашняя, не боится людей))' ,
thread : [ {
subject : 'Re: кошку хочешь?))' ,
from : 'Margarita Philippova' ,
fromEmail : 'philippova.marga@gmail.com' ,
to : 'Виталий Филиппов' ,
time : '2016-06-14 22:31' ,
level : 1 ,
body : 'Нет, конечно, не хочу. Я уеду в Баку, а кошка как? Уеду в Астану - а кошка как? Наташа меня Сухорукова приглашает в Барселону - а кошку куда? Я только испытала радость облегчения от того, что у меня больше нет горшочных цветов - и кошку мне? НЕт! Папику предложи - у него уже много зверья, одной кошкой больше - одной меньше - какая разница?'
} ]
} ;
2016-06-20 23:11:04 +03:00
var listGroups = [ {
name : 'TODAY' ,
2016-06-24 15:43:44 +03:00
messageCount : 10 ,
2016-06-23 01:17:22 +03:00
messages : [ {
subject : 'The Glossary of Happiness By Emily Anthes , May 12, 2016' ,
from : 'Margarita Philippova' ,
fromEmail : 'philippova.marga@gmail.com' ,
to : 'Виталий Филиппов' ,
time : '2016-06-20 00:11:18' ,
unread : true ,
body : ' < pre > < a href = "http://www.newyorker.com/tech/elements/the-glossary-of-happiness" > http : //www.newyorker.com/tech/elements/the-glossary-of-happiness</a><br />\
< br / > \
-- < br / > \
Best regards , < br / > \
Margarita Philippova < / p r e > '
} ]
} , {
name : 'LAST WEEK' ,
2016-06-24 15:43:44 +03:00
messageCount : 15 ,
messages : msg2
2016-06-20 23:11:04 +03:00
} ] ;
2016-06-20 01:42:23 +03:00
2016-06-22 00:14:07 +03:00
var AllTabs = React . createClass ( {
componentDidMount : function ( )
{
2016-06-22 13:37:40 +03:00
Store . on ( 'layout' , this . setLayout ) ;
} ,
componentWillUnmount : function ( )
{
Store . un ( 'layout' , this . setLayout ) ;
2016-06-22 00:14:07 +03:00
} ,
setLayout : function ( )
{
2016-06-22 00:50:07 +03:00
var oldLayout = this . state . layout ;
2016-06-22 00:14:07 +03:00
this . setState ( { layout : Store . layout } ) ;
2016-06-22 00:50:07 +03:00
window . scrollBy ( 0 , 0 ) ;
var self = this ;
requestAnimationFrame ( function ( )
{
var btn ;
if ( oldLayout == 'message-on-right' &&
Store . layout != 'message-on-right' )
{
btn = self . refs . list . refs . setBtn ;
}
else if ( oldLayout != 'message-on-right' &&
Store . layout == 'message-on-right' )
{
btn = self . refs . view . refs . setBtn ;
}
if ( btn )
{
btn . setState ( { pressed : false } ) ;
btn . toggle ( ) ;
}
} ) ;
2016-06-22 00:14:07 +03:00
} ,
getInitialState : function ( )
{
return { layout : Store . layout } ;
} ,
render : function ( )
{
return React . createElement ( TabPanel , { tabs : [
{
className : this . state . layout ,
noclose : true ,
icon : 'mail_unread' ,
title : 'Unread (64)' ,
2016-06-22 00:50:07 +03:00
children : [ < MessageList ref = "list" groups = { listGroups } / > , < MessageView ref = "view" / > ]
2016-06-22 00:14:07 +03:00
} ,
{
icon : 'mail_drafts' ,
i16 : true ,
title : 'Compose Message' ,
children : < ComposeWindow accounts = { composeAccounts } / >
}
] } ) ;
}
} ) ;
2016-06-20 23:11:04 +03:00
ReactDOM . render (
< div >
{ dropdown _account }
{ dropdown _reply }
{ dropdown _forward }
{ dropdown _delete }
{ dropdown _check _send }
{ dropdown _threads }
{ dropdown _list _sort }
{ dropdown _settings }
< FolderList accounts = { accounts } progress = "33" / >
2016-06-22 00:14:07 +03:00
< AllTabs / >
2016-06-20 23:11:04 +03:00
< / d i v > ,
document . body
) ;