Interface fixes

This commit is contained in:
RainLoop Team 2015-03-16 01:58:50 +04:00
parent bce1abd024
commit 3090b44dae
23 changed files with 388 additions and 248 deletions

View file

@ -7,8 +7,10 @@
window = require('window'), window = require('window'),
_ = require('_'), _ = require('_'),
$ = require('$'), $ = require('$'),
key = require('key'),
Globals = require('Common/Globals'), Globals = require('Common/Globals'),
Enums = require('Common/Enums'),
Utils = require('Common/Utils'), Utils = require('Common/Utils'),
Links = require('Common/Links'), Links = require('Common/Links'),
Events = require('Common/Events'), Events = require('Common/Events'),
@ -96,6 +98,10 @@
Globals.$doc.on('mousemove keypress click', _.debounce(function () { Globals.$doc.on('mousemove keypress click', _.debounce(function () {
Events.pub('rl.auto-logout-refresh'); Events.pub('rl.auto-logout-refresh');
}, 5000)); }, 5000));
key('esc, enter', Enums.KeyState.All, _.bind(function () {
Utils.detectDropdownVisibility();
}, this));
} }
_.extend(AbstractApp.prototype, AbstractBoot.prototype); _.extend(AbstractApp.prototype, AbstractBoot.prototype);
@ -350,8 +356,6 @@
ssm.ready(); ssm.ready();
require('Stores/Language').populate(); require('Stores/Language').populate();
require('Stores/Theme').populate(); require('Stores/Theme').populate();
require('Stores/Social').populate(); require('Stores/Social').populate();

View file

@ -258,6 +258,7 @@
}); });
Globals.keyScopeReal.subscribe(function (sValue) { Globals.keyScopeReal.subscribe(function (sValue) {
// window.console.log(sValue);
key.setScope(sValue); key.setScope(sValue);
}); });

13
dev/External/ko.js vendored
View file

@ -131,6 +131,11 @@
if (Globals && Globals.aBootstrapDropdowns) if (Globals && Globals.aBootstrapDropdowns)
{ {
Globals.aBootstrapDropdowns.push($(oElement)); Globals.aBootstrapDropdowns.push($(oElement));
$(oElement).click(function () {
require('Common/Utils').detectDropdownVisibility();
});
// ko.utils.domNodeDisposal.addDisposeCallback(oElement, function () { // ko.utils.domNodeDisposal.addDisposeCallback(oElement, function () {
// }); // });
} }
@ -141,17 +146,13 @@
'update': function (oElement, fValueAccessor) { 'update': function (oElement, fValueAccessor) {
if (ko.unwrap(fValueAccessor())) if (ko.unwrap(fValueAccessor()))
{ {
var var $oEl = $(oElement);
$oEl = $(oElement),
Utils = require('Common/Utils')
;
if (!$oEl.hasClass('open')) if (!$oEl.hasClass('open'))
{ {
$oEl.find('.dropdown-toggle').dropdown('toggle'); $oEl.find('.dropdown-toggle').dropdown('toggle');
Utils.detectDropdownVisibility();
} }
require('Common/Utils').detectDropdownVisibility();
fValueAccessor()(false); fValueAccessor()(false);
} }
} }

View file

@ -649,10 +649,10 @@
{ {
aResult.push('emptySubject'); aResult.push('emptySubject');
} }
if (1 < this.threadsLen()) // if (1 < this.threadsLen())
{ // {
aResult.push('hasChildrenMessage'); // aResult.push('hasChildrenMessage');
} // }
if (this.hasUnseenSubMessage()) if (this.hasUnseenSubMessage())
{ {
aResult.push('hasUnseenSubMessage'); aResult.push('hasUnseenSubMessage');

View file

@ -0,0 +1,93 @@
(function () {
'use strict';
var
_ = require('_'),
Utils = require('Common/Utils'),
MessageModel = require('Model/Message'),
AbstractModel = require('Knoin/AbstractModel')
;
/**
* @constructor
*/
function MessageSimpleModel()
{
AbstractModel.call(this, 'MessageSimpleModel');
this.selected = false;
this.folderFullNameRaw = '';
this.uid = '';
this.size = 0;
this.sender = '';
this.subject = '';
this.dateUTC = 0;
}
_.extend(MessageSimpleModel.prototype, AbstractModel.prototype);
/**
* @static
* @param {AjaxJsonMessage} oJsonMessage
* @return {?MessageSimpleModel}
*/
MessageSimpleModel.newInstanceFromJson = function (oJsonMessage)
{
var oMessageModel = new MessageSimpleModel();
return oMessageModel.initByJson(oJsonMessage) ? oMessageModel : null;
};
MessageSimpleModel.prototype.clear = function ()
{
this.selected = false;
this.folderFullNameRaw = '';
this.uid = '';
this.size = 0;
this.sender = '';
this.subject = '';
this.dateUTC = 0;
};
/**
* @param {AjaxJsonMessage} oJsonMessage
* @return {boolean}
*/
MessageSimpleModel.prototype.initByJson = function (oJsonMessage)
{
var bResult = false;
if (oJsonMessage && 'Object/Message' === oJsonMessage['@Object'])
{
this.selected = false;
this.folderFullNameRaw = oJsonMessage.Folder;
this.uid = oJsonMessage.Uid;
this.size = Utils.pInt(oJsonMessage.Size);
this.sender = MessageModel.emailsToLine(
MessageModel.initEmailsFromJson(oJsonMessage.From), true);
this.subject = oJsonMessage.Subject;
this.dateUTC = Utils.pInt(oJsonMessage.DateTimeStampInUTC);
bResult = true;
}
return bResult;
};
module.exports = MessageSimpleModel;
}());

View file

@ -30,7 +30,7 @@
return this; return this;
}; };
AbstractAjaxPromises.prototype.fastPromise = function (mData) AbstractAjaxPromises.prototype.fastResolve = function (mData)
{ {
var oDeferred = Q.defer(); var oDeferred = Q.defer();
oDeferred.resolve(mData); oDeferred.resolve(mData);

View file

@ -5,11 +5,8 @@
var var
_ = require('_'), _ = require('_'),
ko = require('ko'),
AbstractAjaxPromises = require('Promises/AbstractAjax'), AbstractAjaxPromises = require('Promises/AbstractAjax')
MessageModel = require('Model/Message')
; ;
/** /**
@ -20,39 +17,41 @@
{ {
AbstractAjaxPromises.call(this); AbstractAjaxPromises.call(this);
this.messageListSimple.loading = ko.observable(false).extend({'rateLimit': 1}); this.messageListSimpleHash = '';
this.messageListSimple.hash = ''; this.messageListSimpleCache = null;
this.messageListSimple.cache = null;
} }
PromisesUserAjax.prototype.messageListSimple = function (sFolder, aUids) _.extend(PromisesUserAjax.prototype, AbstractAjaxPromises.prototype);
PromisesUserAjax.prototype.messageListSimple = function (sFolder, aUids, fTrigger)
{ {
var self = this, sHash = sFolder + '~' + aUids.join('/'); var self = this, sHash = sFolder + '~' + aUids.join('/');
if (sHash === this.messageListSimple.hash && this.messageListSimple.cache) if (sHash === this.messageListSimpleHash && this.messageListSimpleCache)
{ {
return this.fastPromise(this.messageListSimple.cache); return this.fastResolve(this.messageListSimpleCache);
} }
return this.abort('MessageListSimple') return this.abort('MessageListSimple')
.postRequest('MessageListSimple', this.messageListSimple.loading, { .postRequest('MessageListSimple', fTrigger, {
'Folder': sFolder, 'Folder': sFolder,
'Uids': aUids 'Uids': aUids
}).then(function (aData) { }).then(function (aData) {
var aResult = _.compact(_.map(aData, function (aItem) { var
return MessageModel.newInstanceFromJson(aItem); MessageSimpleModel = require('Model/MessageSimple'),
})); aResult = _.compact(_.map(aData, function (aItem) {
return MessageSimpleModel.newInstanceFromJson(aItem);
}))
;
self.messageListSimple.hash = sHash; self.messageListSimpleHash = sHash;
self.messageListSimple.cache = aResult; self.messageListSimpleCache = aResult;
return aResult; return aResult;
}) })
; ;
}; };
_.extend(PromisesUserAjax.prototype, AbstractAjaxPromises.prototype);
module.exports = new PromisesUserAjax(); module.exports = new PromisesUserAjax();
}()); }());

View file

@ -393,6 +393,16 @@ html.rl-no-preview-pane {
text-overflow: ellipsis; text-overflow: ellipsis;
} }
.threads-len {
.threads-len-data {
background-color: #999;
color: #fff;
border-radius: 6px;
padding: 0px 4px;
margin-right: 5px;
}
}
.subject-prefix { .subject-prefix {
color: #888; color: #888;
/*font-style: italic;*/ /*font-style: italic;*/
@ -437,6 +447,16 @@ html.rl-no-preview-pane {
text-shadow: 0px 1px 0px #eee; text-shadow: 0px 1px 0px #eee;
} }
&.hasUnseenSubMessage {
background-color: #FFFFD9;
.sidebarParent {
background-color: lighten(orange, 30%);
}
&.focused .sidebarParent {
background-color: darken(orange, 10%) !important;
}
}
&.unseen { &.unseen {
background-color: #FFFFD9; background-color: #FFFFD9;
.sender, .subject, .subject-suffix { .sender, .subject, .subject-suffix {
@ -451,16 +471,7 @@ html.rl-no-preview-pane {
} }
} }
&.hasUnseenSubMessage { /*
background-color: #FFFFD9;
.sidebarParent {
background-color: lighten(orange, 30%);
}
&.focused .sidebarParent {
background-color: darken(orange, 10%) !important;
}
}
&.hasParentMessage { &.hasParentMessage {
background-color: #ecf0f1; background-color: #ecf0f1;
@ -484,6 +495,7 @@ html.rl-no-preview-pane {
} }
} }
} }
*/
&.checked { &.checked {
.sidebarParent { .sidebarParent {

View file

@ -17,7 +17,7 @@ html.rl-no-preview-pane {
position: absolute; position: absolute;
top: 0; top: 0;
right: 0; right: 0;
left: 0; left: -2px;
height: 30px; height: 30px;
padding: 10px 0; padding: 10px 0;
color: #fff; color: #fff;
@ -365,15 +365,24 @@ html.rl-no-preview-pane {
border-color: darken(@rlMainDarkColor, 5%); border-color: darken(@rlMainDarkColor, 5%);
} }
.thread-controls {
.dropdown-toggle {
padding-left: 10px;
padding-right: 10px;
}
&.open .dropdown-toggle {
padding-left: 10px;
padding-right: 10px;
}
}
.thread-list { .thread-list {
.e-link { .e-link {
padding: 3px 5px 3px 10px; padding: 3px 8px 3px 10px;
overflow: hidden;
text-overflow: ellipsis;
} }
.hread-date { .thread-date {
font-size: 13px; font-size: 13px;
color: #999; color: #999;
} }

View file

@ -42,7 +42,7 @@
text-shadow: 0 1px 0 #000; text-shadow: 0 1px 0 #000;
display: inline-block; display: inline-block;
height: 28px; height: 29px;
max-width: 250px; max-width: 250px;
border-radius: 4px; border-radius: 4px;
font-size: 16px; font-size: 16px;

View file

@ -105,7 +105,7 @@ select {
} }
.btn { .btn {
border-radiu: @btnBorderRadius; border-radius: @btnBorderRadius;
background-image: none; background-image: none;
padding-left: 13px; padding-left: 13px;
padding-right: 13px; padding-right: 13px;
@ -180,26 +180,22 @@ html.rgba.textshadow {
} }
} }
// Set corners individual because sometimes a single button can be in a .btn-group and we need :first-child and :last-child to both match .btn-group > .btn {
.btn-group > .btn:first-child { border-radius: 0 !important;
border-top-left-radius: @btnBorderRadius;
border-bottom-left-radius: @btnBorderRadius;
} }
// Need .dropdown-toggle since :last-child doesn't apply given a .dropdown-menu immediately after it
.btn-group > .btn:last-child, .btn-group > .btn.single {
.btn-group > .dropdown-toggle { border-radius: @btnBorderRadius !important;
border-top-right-radius: @btnBorderRadius;
border-bottom-right-radius: @btnBorderRadius;
} }
// Reset corners for large buttons
.btn-group > .btn.large:first-child { .btn-group > .btn.first {
border-top-left-radius: @btnBorderRadius; border-top-left-radius: @btnBorderRadius !important;
border-bottom-left-radius: @btnBorderRadius; border-bottom-left-radius: @btnBorderRadius !important;
} }
.btn-group > .btn.large:last-child,
.btn-group > .large.dropdown-toggle { .btn-group > .btn.last {
border-top-right-radius: @btnBorderRadius; border-top-right-radius: @btnBorderRadius !important;
border-bottom-right-radius: @btnBorderRadius; border-bottom-right-radius: @btnBorderRadius !important;
} }
.dropdown.colored-toggle.open .btn.dropdown-toggle { .dropdown.colored-toggle.open .btn.dropdown-toggle {

View file

@ -75,7 +75,7 @@
this.fullScreenMode = MessageStore.messageFullScreenMode; this.fullScreenMode = MessageStore.messageFullScreenMode;
this.messageListOfThreadsLoading = Promises.messageListSimple.loading; this.messageListOfThreadsLoading = ko.observable(false).extend({'rateLimit': 1});
this.lastReplyAction_ = ko.observable(''); this.lastReplyAction_ = ko.observable('');
this.lastReplyAction = ko.computed({ this.lastReplyAction = ko.computed({
@ -308,12 +308,13 @@
if (aStatus && aStatus[0]) if (aStatus && aStatus[0])
{ {
self.viewThreadMessages([]); self.viewThreadMessages([]);
Promises.messageListSimple(sFolder, aUids).then(function (aList) {
Promises.messageListSimple(sFolder, aUids, this.messageListOfThreadsLoading).then(function (aList) {
_.each(aList, function (oItem) { _.each(aList, function (oItem) {
if (oItem && oItem.uid) if (oItem && oItem.uid)
{ {
oItem.selected(sUid === oItem.uid); oItem.selected = sUid === oItem.uid;
} }
}); });
@ -577,18 +578,21 @@
kn.showScreenPopup(require('View/Popup/Compose'), [sType, MessageStore.message()]); kn.showScreenPopup(require('View/Popup/Compose'), [sType, MessageStore.message()]);
}; };
MessageViewMailBoxUserView.prototype.checkHeaderHeight = function ()
{
if (this.oHeaderDom)
{
this.viewBodyTopValue(this.message() ? this.oHeaderDom.height() +
20 /* padding-(top/bottom): 20px */ + 1 /* borded-bottom: 1px */ : 0);
}
};
MessageViewMailBoxUserView.prototype.onBuild = function (oDom) MessageViewMailBoxUserView.prototype.onBuild = function (oDom)
{ {
var var
self = this, self = this,
sErrorMessage = Translator.i18n('PREVIEW_POPUP/IMAGE_ERROR'), sErrorMessage = Translator.i18n('PREVIEW_POPUP/IMAGE_ERROR'),
fCheckHeaderHeight = function () { fCheckHeaderHeight = _.bind(this.checkHeaderHeight, this)
if (self.oHeaderDom)
{
self.viewBodyTopValue(self.message() ? self.oHeaderDom.height() +
20 /* padding-(top/bottom): 20px */ + 1 /* borded-bottom: 1px */ : 0);
}
}
; ;
this.fullScreenMode.subscribe(function (bValue) { this.fullScreenMode.subscribe(function (bValue) {

View file

@ -2,7 +2,7 @@
"name": "RainLoop", "name": "RainLoop",
"title": "RainLoop Webmail", "title": "RainLoop Webmail",
"version": "1.8.2", "version": "1.8.2",
"release": "287", "release": "288",
"description": "Simple, modern & fast web-based email client", "description": "Simple, modern & fast web-based email client",
"homepage": "http://rainloop.net", "homepage": "http://rainloop.net",
"main": "gulpfile.js", "main": "gulpfile.js",

View file

@ -148,7 +148,7 @@
.thm-rgba-background-color(@folders-selected-background-color, @folders-selected-rgba-background-color); .thm-rgba-background-color(@folders-selected-background-color, @folders-selected-rgba-background-color);
} }
&.selectable.focused { &.focused {
color: @folders-focused-color !important; color: @folders-focused-color !important;
.thm-rgba-background-color(@folders-focused-background-color, @folders-focused-rgba-background-color); .thm-rgba-background-color(@folders-focused-background-color, @folders-focused-rgba-background-color);
} }

View file

@ -23,15 +23,15 @@
<nobr> <nobr>
<div class="btn-toolbar"> <div class="btn-toolbar">
<div class="btn-group hide-on-panel-disabled"> <div class="btn-group hide-on-panel-disabled">
<a class="btn" data-bind="click: createFolder"> <a class="btn first" data-bind="click: createFolder">
<i data-bind="css: {'icon-folder-add': !foldersChanging(), 'icon-spinner animated': foldersChanging()}"></i> <i data-bind="css: {'icon-folder-add': !foldersChanging(), 'icon-spinner animated': foldersChanging()}"></i>
</a> </a>
<a class="btn" data-bind="click: configureFolders"> <a class="btn last" data-bind="click: configureFolders">
<i class="icon-cog"></i> <i class="icon-cog"></i>
</a> </a>
</div> </div>
<div class="btn-group"> <div class="btn-group">
<a class="btn buttonResize" data-bind="click: function () { leftPanelDisabled(!leftPanelDisabled()); }"> <a class="btn single buttonResize" data-bind="click: function () { leftPanelDisabled(!leftPanelDisabled()); }">
<i data-bind="css: {'icon-resize-out': leftPanelDisabled(), 'icon-resize-in': !leftPanelDisabled()}"></i> <i data-bind="css: {'icon-resize-out': leftPanelDisabled(), 'icon-resize-in': !leftPanelDisabled()}"></i>
</a> </a>
</div> </div>

View file

@ -4,13 +4,13 @@
<div class="toolbar"> <div class="toolbar">
<div class="btn-toolbar"> <div class="btn-toolbar">
<div class="btn-group"> <div class="btn-group">
<a class="btn btn-dark-disabled-border buttonReload" data-tooltip-placement="bottom" data-bind="command: reloadCommand, tooltip: 'MESSAGE_LIST/BUTTON_RELOAD'"> <a class="btn single btn-dark-disabled-border buttonReload" data-tooltip-placement="bottom" data-bind="command: reloadCommand, tooltip: 'MESSAGE_LIST/BUTTON_RELOAD'">
<i class="icon-spinner" data-bind="css: {'animated': messageListCompleteLoadingThrottle}"></i> <i class="icon-spinner" data-bind="css: {'animated': messageListCompleteLoadingThrottle}"></i>
</a> </a>
</div> </div>
<div class="btn-group">&nbsp;</div> <div class="btn-group">&nbsp;</div>
<div class="btn-group dropdown colored-toggle" data-bind="registrateBootstrapDropdown: true, openDropdownTrigger: moveDropdownTrigger"> <div class="btn-group dropdown colored-toggle" data-bind="registrateBootstrapDropdown: true, openDropdownTrigger: moveDropdownTrigger">
<a id="move-dropdown-id" href="#" tabindex="-1" class="btn btn-dark-disabled-border dropdown-toggle buttonMove" data-toggle="dropdown" data-tooltip-placement="bottom" data-bind="command: moveCommand, tooltip: 'MESSAGE_LIST/BUTTON_MOVE_TO'"> <a id="move-dropdown-id" href="#" tabindex="-1" class="btn single btn-dark-disabled-border dropdown-toggle buttonMove" data-toggle="dropdown" data-tooltip-placement="bottom" data-bind="command: moveCommand, tooltip: 'MESSAGE_LIST/BUTTON_MOVE_TO'">
<i class="icon-copy visible-on-ctrl-btn"></i> <i class="icon-copy visible-on-ctrl-btn"></i>
<i class="icon-folder hidden-on-ctrl-btn"></i> <i class="icon-folder hidden-on-ctrl-btn"></i>
&nbsp;&nbsp; &nbsp;&nbsp;
@ -29,7 +29,7 @@
</div> </div>
<div class="btn-group">&nbsp;</div> <div class="btn-group">&nbsp;</div>
<div class="btn-group"> <div class="btn-group">
<a class="btn btn-dark-disabled-border button-archive" data-tooltip-placement="bottom" data-bind="visible: !isArchiveFolder() && !isArchiveDisabled() && !isDraftFolder(), command: archiveCommand, tooltip: 'MESSAGE_LIST/BUTTON_ARCHIVE'"> <a class="btn first btn-dark-disabled-border button-archive" data-tooltip-placement="bottom" data-bind="visible: !isArchiveFolder() && !isArchiveDisabled() && !isDraftFolder(), command: archiveCommand, tooltip: 'MESSAGE_LIST/BUTTON_ARCHIVE'">
<i class="icon-archive"></i> <i class="icon-archive"></i>
</a> </a>
<a class="btn btn-dark-disabled-border button-spam" data-tooltip-placement="bottom" data-bind="visible: !isSpamFolder() && !isSpamDisabled() && !isDraftFolder() && !isSentFolder(), command: spamCommand, tooltip: 'MESSAGE_LIST/BUTTON_SPAM'"> <a class="btn btn-dark-disabled-border button-spam" data-tooltip-placement="bottom" data-bind="visible: !isSpamFolder() && !isSpamDisabled() && !isDraftFolder() && !isSentFolder(), command: spamCommand, tooltip: 'MESSAGE_LIST/BUTTON_SPAM'">
@ -38,14 +38,14 @@
<a class="btn btn-dark-disabled-border button-not-spam" data-tooltip-placement="bottom" data-bind="visible: isSpamFolder() && !isSpamDisabled() && !isDraftFolder() && !isSentFolder(), command: notSpamCommand, tooltip: 'MESSAGE_LIST/BUTTON_NOT_SPAM'"> <a class="btn btn-dark-disabled-border button-not-spam" data-tooltip-placement="bottom" data-bind="visible: isSpamFolder() && !isSpamDisabled() && !isDraftFolder() && !isSentFolder(), command: notSpamCommand, tooltip: 'MESSAGE_LIST/BUTTON_NOT_SPAM'">
<i class="icon-happy-smiley"></i> <i class="icon-happy-smiley"></i>
</a> </a>
<a class="btn btn-dark-disabled-border button-delete" data-tooltip-placement="bottom" data-bind="command: deleteCommand, tooltip: 'MESSAGE_LIST/BUTTON_DELETE'"> <a class="btn last btn-dark-disabled-border button-delete" data-tooltip-placement="bottom" data-bind="command: deleteCommand, tooltip: 'MESSAGE_LIST/BUTTON_DELETE'">
<i class="icon-trash"></i> <i class="icon-trash"></i>
<!--<span data-bind="text: printableMessageCountForDeletion()"></span>--> <!--<span data-bind="text: printableMessageCountForDeletion()"></span>-->
</a> </a>
</div> </div>
<div class="btn-group">&nbsp;</div> <div class="btn-group">&nbsp;</div>
<div class="btn-group dropdown colored-toggle" data-bind="registrateBootstrapDropdown: true, openDropdownTrigger: moreDropdownTrigger"> <div class="btn-group dropdown colored-toggle" data-bind="registrateBootstrapDropdown: true, openDropdownTrigger: moreDropdownTrigger">
<a id="more-list-dropdown-id" class="btn btn-dark-disabled-border dropdown-toggle buttonMore" href="#" tabindex="-1" data-toggle="dropdown" data-tooltip-placement="bottom" data-bind="tooltip: 'MESSAGE_LIST/BUTTON_MORE'"> <a id="more-list-dropdown-id" class="btn single btn-dark-disabled-border dropdown-toggle buttonMore" href="#" tabindex="-1" data-toggle="dropdown" data-tooltip-placement="bottom" data-bind="tooltip: 'MESSAGE_LIST/BUTTON_MORE'">
<i class="icon-list"></i> <i class="icon-list"></i>
</a> </a>
<ul class="dropdown-menu g-ui-menu" role="menu" aria-labelledby="more-list-dropdown-id"> <ul class="dropdown-menu g-ui-menu" role="menu" aria-labelledby="more-list-dropdown-id">

View file

@ -24,10 +24,10 @@
<div class="senderParent actionHandle dragHandle"> <div class="senderParent actionHandle dragHandle">
<span class="replyFlag"><i class="icon-reply"></i>&nbsp;</span> <span class="replyFlag"><i class="icon-reply"></i>&nbsp;</span>
<span class="forwardFlag"><i class="icon-forward"></i>&nbsp;</span> <span class="forwardFlag"><i class="icon-forward"></i>&nbsp;</span>
<span class="sender" data-bind="text: senderEmailsString, attr: {'title': senderClearEmailsString}"></span> <span class="threads-len" data-bind="visible: 1 < threadsLen()">
<span class="thre" data-bind="visible: 1 < threadsLen()"> <span class="threads-len-data" data-bind="text: threadsLen"></span>
(<span data-bind="text: threadsLen"></span>)
</span> </span>
<span class="sender" data-bind="text: senderEmailsString, attr: {'title': senderClearEmailsString}"></span>
&nbsp; &nbsp;
</div> </div>
<div class="attachmentParent actionHandle dragHandle"> <div class="attachmentParent actionHandle dragHandle">

View file

@ -24,10 +24,10 @@
<div class="senderParent actionHandle dragHandle"> <div class="senderParent actionHandle dragHandle">
<span class="replyFlag"><i class="icon-reply"></i>&nbsp;</span> <span class="replyFlag"><i class="icon-reply"></i>&nbsp;</span>
<span class="forwardFlag"><i class="icon-forward"></i>&nbsp;</span> <span class="forwardFlag"><i class="icon-forward"></i>&nbsp;</span>
<span class="sender" data-bind="text: senderEmailsString, attr: {'title': senderClearEmailsString}"></span> <span class="threads-len" data-bind="visible: 1 < threadsLen()">
<span class="thre" data-bind="visible: 1 < threadsLen()"> <span class="threads-len-data" data-bind="text: threadsLen"></span>
(<span data-bind="text: threadsLen"></span>)
</span> </span>
<span class="sender" data-bind="text: senderEmailsString, attr: {'title': senderClearEmailsString}"></span>
&nbsp; &nbsp;
</div> </div>
<div class="attachmentParent actionHandle dragHandle"> <div class="attachmentParent actionHandle dragHandle">

View file

@ -5,19 +5,19 @@
<nobr> <nobr>
<div class="messageButtons btn-toolbar"> <div class="messageButtons btn-toolbar">
<div class="btn-group" data-tooltip-placement="bottom" data-bind="tooltip: 'MESSAGE/BUTTON_CLOSE'"> <div class="btn-group" data-tooltip-placement="bottom" data-bind="tooltip: 'MESSAGE/BUTTON_CLOSE'">
<a class="btn btn-dark-disabled-border buttonClose" data-bind="command: closeMessage"> <a class="btn single btn-dark-disabled-border buttonClose" data-bind="command: closeMessage">
<i class="icon-remove"></i> <i class="icon-remove"></i>
</a> </a>
</div> </div>
<div class="btn-group">&nbsp;</div> <div class="btn-group">&nbsp;</div>
<div class="btn-group" data-tooltip-placement="bottom" data-bind="visible: isDraftFolder(), tooltip: 'MESSAGE/BUTTON_EDIT'"> <div class="btn-group" data-tooltip-placement="bottom" data-bind="visible: isDraftFolder(), tooltip: 'MESSAGE/BUTTON_EDIT'">
<a class="btn btn-success buttonEdit" data-bind="command: messageEditCommand"> <a class="btn single btn-success buttonEdit" data-bind="command: messageEditCommand">
<i class="icon-pencil icon-white"></i> <i class="icon-pencil icon-white"></i>
</a> </a>
</div> </div>
<div class="btn-group" data-bind="visible: !usePreviewPane()">&nbsp;</div> <div class="btn-group" data-bind="visible: !usePreviewPane()">&nbsp;</div>
<div class="btn-group" data-bind="visible: !usePreviewPane()"> <div class="btn-group" data-bind="visible: !usePreviewPane()">
<a class="btn btn-dark-disabled-border button-archive" data-tooltip-placement="bottom" data-bind="visible: !isDraftFolder() && !isArchiveFolder() && !isArchiveDisabled(), command: archiveCommand, tooltip: 'MESSAGE/BUTTON_ARCHIVE'"> <a class="btn first btn-dark-disabled-border button-archive" data-tooltip-placement="bottom" data-bind="visible: !isDraftFolder() && !isArchiveFolder() && !isArchiveDisabled(), command: archiveCommand, tooltip: 'MESSAGE/BUTTON_ARCHIVE'">
<i class="icon-archive"></i> <i class="icon-archive"></i>
</a> </a>
<a class="btn btn-dark-disabled-border button-spam" data-tooltip-placement="bottom" data-bind="visible: !isDraftFolder() && !isSentFolder() && !isSpamFolder() && !isSpamDisabled(), command: spamCommand, tooltip: 'MESSAGE/BUTTON_SPAM'"> <a class="btn btn-dark-disabled-border button-spam" data-tooltip-placement="bottom" data-bind="visible: !isDraftFolder() && !isSentFolder() && !isSpamFolder() && !isSpamDisabled(), command: spamCommand, tooltip: 'MESSAGE/BUTTON_SPAM'">
@ -26,16 +26,16 @@
<a class="btn btn-dark-disabled-border button-not-spam" data-tooltip-placement="bottom" data-bind="visible: !isDraftFolder() && !isSentFolder() && isSpamFolder() && !isSpamDisabled(), command: notSpamCommand, tooltip: 'MESSAGE/BUTTON_NOT_SPAM'"> <a class="btn btn-dark-disabled-border button-not-spam" data-tooltip-placement="bottom" data-bind="visible: !isDraftFolder() && !isSentFolder() && isSpamFolder() && !isSpamDisabled(), command: notSpamCommand, tooltip: 'MESSAGE/BUTTON_NOT_SPAM'">
<i class="icon-happy-smiley"></i> <i class="icon-happy-smiley"></i>
</a> </a>
<a class="btn btn-dark-disabled-border button-delete" data-tooltip-placement="bottom" data-bind="command: deleteCommand, tooltip: 'MESSAGE/BUTTON_DELETE'"> <a class="btn last btn-dark-disabled-border button-delete" data-tooltip-placement="bottom" data-bind="command: deleteCommand, tooltip: 'MESSAGE/BUTTON_DELETE'">
<i class="icon-trash"></i> <i class="icon-trash"></i>
</a> </a>
</div> </div>
<div class="btn-group">&nbsp;</div> <div class="btn-group">&nbsp;</div>
<div class="btn-group" data-bind="visible: !usePreviewPane()"> <div class="btn-group" data-bind="visible: !usePreviewPane()">
<a class="btn btn-dark-disabled-border buttonUp" data-bind="command: goUpCommand"> <a class="btn btn-thin first btn-dark-disabled-border buttonUp" data-bind="command: goUpCommand">
<i class="icon-left-middle"></i> <i class="icon-left-middle"></i>
</a> </a>
<a class="btn btn-dark-disabled-border buttonDown" data-bind="command: goDownCommand"> <a class="btn btn-thin last btn-dark-disabled-border buttonDown" data-bind="command: goDownCommand">
<i class="icon-right-middle"></i> <i class="icon-right-middle"></i>
</a> </a>
</div> </div>
@ -60,20 +60,11 @@
<div class="message-fixed-button-toolbar clearfix" data-bind="visible: message"> <div class="message-fixed-button-toolbar clearfix" data-bind="visible: message">
<nobr> <nobr>
<div class="btn-group pull-right"> <div class="btn-group pull-right">
<a class="btn btn-dark-disabled-border buttonReply" data-tooltip-placement="bottom" <div class="btn-group pull-right" data-bind="registrateBootstrapDropdown: true">
data-bind="visible: 'reply' === lastReplyAction(), command: replyCommand, tooltip: 'MESSAGE/BUTTON_REPLY'"> <a class="btn btn-thin last btn-dark-disabled-border dropdown-toggle buttonMore"
<i class="icon-reply"></i> id="more-view-dropdown-id" href="#" tabindex="-1"
</a> data-toggle="dropdown" data-tooltip-placement="bottom"
<a class="btn btn-dark-disabled-border buttonReplyAll" data-tooltip-placement="bottom" style="margin-left: -1px;"
data-bind="visible: 'replyall' === lastReplyAction(), command: replyAllCommand, tooltip: 'MESSAGE/BUTTON_REPLY_ALL'">
<i class="icon-reply-all"></i>
</a>
<a class="btn btn-dark-disabled-border buttonForward" data-tooltip-placement="bottom"
data-bind="visible: 'forward' === lastReplyAction(), command: forwardCommand, tooltip: 'MESSAGE/BUTTON_FORWARD'">
<i class="icon-forward"></i>
</a>
<a id="more-view-dropdown-id" class="btn btn-dark-disabled-border dropdown-toggle buttonMore"
href="#" tabindex="-1" data-toggle="dropdown" data-tooltip-placement="bottom"
data-bind="command: messageVisibilityCommand, tooltip: 'MESSAGE/BUTTON_MORE'"> data-bind="command: messageVisibilityCommand, tooltip: 'MESSAGE/BUTTON_MORE'">
<span class="caret"></span> <span class="caret"></span>
</a> </a>
@ -177,43 +168,70 @@
</li> </li>
</ul> </ul>
</div> </div>
<a class="btn first btn-dark-disabled-border buttonReply pull-right" data-tooltip-placement="bottom"
data-bind="visible: 'reply' === lastReplyAction(), command: replyCommand, tooltip: 'MESSAGE/BUTTON_REPLY'">
<i class="icon-reply"></i>
</a>
<a class="btn first btn-dark-disabled-border buttonReplyAll pull-right" data-tooltip-placement="bottom"
data-bind="visible: 'replyall' === lastReplyAction(), command: replyAllCommand, tooltip: 'MESSAGE/BUTTON_REPLY_ALL'">
<i class="icon-reply-all"></i>
</a>
<a class="btn first btn-dark-disabled-border buttonForward pull-right" data-tooltip-placement="bottom"
data-bind="visible: 'forward' === lastReplyAction(), command: forwardCommand, tooltip: 'MESSAGE/BUTTON_FORWARD'">
<i class="icon-forward"></i>
</a>
</div>
<div class="btn-group pull-right" data-bind="visible: isDraftFolder()" style="margin-right: 5px"> <div class="btn-group pull-right" data-bind="visible: isDraftFolder()" style="margin-right: 5px">
<a class="btn btn-success buttonEdit" data-bind="command: messageEditCommand"> <a class="btn single btn-success buttonEdit" data-bind="command: messageEditCommand">
<i class="icon-pencil icon-white"></i> <i class="icon-pencil icon-white"></i>
</a> </a>
</div> </div>
<div class="btn-group pull-right" data-bind="visible: viewThreadsControlVisibility" style="margin-right: 5px">
<a class="btn btn-thin" data-tooltip-placement="bottom" <div class="btn-group thread-controls pull-right g-ui-user-select-none" style="margin-right: 5px"
data-bind="command: threadForwardCommand, tooltip: 'MESSAGE/BUTTON_THREAD_NEXT'"> data-bind="visible: viewThreadsControlVisibility">
<i class="icon-left-middle"></i>
</a> <a class="btn last btn-thin pull-right" data-tooltip-placement="bottom"
<a class="btn btn-dark-disabled-border dropdown-toggle" id="thread-list-view-dropdown-id" data-toggle="dropdown"
href="#" tabindex="-1" data-tooltip-placement="bottom"
data-bind="command: threadListCommand, tooltip: 'MESSAGE/BUTTON_THREAD_LIST'">
<i class="icon-list"
data-bind="css: {'icon-list': !messageListOfThreadsLoading(), 'icon-spinner animated': messageListOfThreadsLoading()}"></i>
</a>
<a class="btn btn-thin" data-tooltip-placement="bottom"
data-bind="command: threadBackCommand, tooltip: 'MESSAGE/BUTTON_THREAD_PREV'"> data-bind="command: threadBackCommand, tooltip: 'MESSAGE/BUTTON_THREAD_PREV'">
<i class="icon-right-middle"></i> <i class="icon-right-middle"></i>
</a> </a>
<ul class="dropdown-menu g-ui-menu thread-list" role="menu" aria-labelledby="thread-list-view-dropdown-id" <div class="btn-group pull-right" data-bind="registrateBootstrapDropdown: true">
<a class="btn btn-thin btn-dark-disabled-border dropdown-toggle" id="thread-list-view-dropdown-id" data-toggle="dropdown"
href="#" tabindex="-1" data-tooltip-placement="bottom"
style="margin-left: -1px; margin-right: -1px;"
data-bind="command: threadListCommand, tooltip: 'MESSAGE/BUTTON_THREAD_LIST'"
>
<i class="icon-list"
data-bind="css: {'icon-list': !messageListOfThreadsLoading(), 'icon-spinner animated': messageListOfThreadsLoading()}"></i>
</a>
<ul class="dropdown-menu pull-right g-ui-menu thread-list" role="menu" aria-labelledby="thread-list-view-dropdown-id"
style="min-width: 400px; max-width: 400px; width: 400px;"> style="min-width: 400px; max-width: 400px; width: 400px;">
<div data-bind="visible: messageListOfThreadsLoading" style="text-align: center; padding: 10px"> <div data-bind="visible: messageListOfThreadsLoading" style="text-align: center; padding: 10px">
<i class="icon-spinner animated" /> <i class="icon-spinner animated" />
</div > </div >
<div data-bind="foreach: viewThreadMessages, visible: !messageListOfThreadsLoading()"> <div data-bind="foreach: viewThreadMessages, visible: !messageListOfThreadsLoading()">
<li class="e-item thread-list-message" role="presentation" data-bind="css: {'selected': selected}"> <li class="e-item thread-list-message" role="presentation" data-bind="css: {'selected': selected}">
<a class="e-link menuitem" href="#" tabindex="-1"> <a class="e-link menuitem" href="#" tabindex="-1" onclick="return false;">
<span class="thread-from" data-bind="text: senderEmailsString"></span> <span class="thread-date pull-right" data-moment-format="SHORT" data-bind="moment: dateUTC"></span>
<span class="hread-date pull-right" data-moment-format="SHORT" data-bind="moment: dateTimeStampInUTC"></span> <div style="text-overflow: ellipsis; overflow: hidden;">
<br /> <span class="thread-from" data-bind="text: sender"></span>
&nbsp;
</div>
<div style="text-overflow: ellipsis; overflow: hidden;">
<span class="thread-subject" data-bind="text: subject"></span> <span class="thread-subject" data-bind="text: subject"></span>
&nbsp;
</div>
</a> </a>
</li> </li>
</div> </div>
</ul> </ul>
</div> </div>
<a class="btn first btn-thin pull-right" data-tooltip-placement="bottom"
data-bind="command: threadForwardCommand, tooltip: 'MESSAGE/BUTTON_THREAD_NEXT'">
<i class="icon-left-middle"></i>
</a>
</div>
</nobr> </nobr>
</div> </div>

View file

@ -49,7 +49,7 @@
<!-- /ko --> <!-- /ko -->
</div> </div>
<div class="btn-group dropdown colored-toggle pull-right" style="margin-right: 4px;"> <div class="btn-group dropdown colored-toggle pull-right" style="margin-right: 4px;">
<a class="btn dropdown-toggle buttonMore" data-toggle="dropdown"> <a class="btn single dropdown-toggle buttonMore" data-toggle="dropdown">
<i class="icon-list"></i> <i class="icon-list"></i>
</a> </a>
<ul class="dropdown-menu g-ui-menu" role="menu"> <ul class="dropdown-menu g-ui-menu" role="menu">
@ -86,7 +86,7 @@
</div> </div>
<div class="btn-group pull-right">&nbsp;</div> <div class="btn-group pull-right">&nbsp;</div>
<div class="btn-group pull-right"> <div class="btn-group pull-right">
<a class="btn" data-tooltip-placement="bottom" data-bind="visible: allowContacts, command: contactsCommand, tooltip: 'FOLDER_LIST/BUTTON_CONTACTS'"> <a class="btn single" data-tooltip-placement="bottom" data-bind="visible: allowContacts, command: contactsCommand, tooltip: 'FOLDER_LIST/BUTTON_CONTACTS'">
<i class="icon-address-book"></i> <i class="icon-address-book"></i>
</a> </a>
</div> </div>
@ -160,11 +160,11 @@
</div> </div>
<div class="pull-left"> <div class="pull-left">
<div class="btn-group" data-toggle="buttons-radio"> <div class="btn-group" data-toggle="buttons-radio">
<button type="button" class="btn" data-bind="click: function () { attachmentsPlace(false); }, <button type="button" class="btn first" data-bind="click: function () { attachmentsPlace(false); },
css: { 'active': !attachmentsPlace() }"> css: { 'active': !attachmentsPlace() }">
<i class="icon-file-text"></i> <i class="icon-file-text"></i>
</button> </button>
<button type="button" class="btn" data-bind="click: function () { attachmentsPlace(true); }, <button type="button" class="btn last" data-bind="click: function () { attachmentsPlace(true); },
css: { 'btn-danger': 0 < attachmentsInErrorCount(), 'active': attachmentsPlace() }"> css: { 'btn-danger': 0 < attachmentsInErrorCount(), 'active': attachmentsPlace() }">
<span data-bind="visible: 0 < attachmentsCount()"> <span data-bind="visible: 0 < attachmentsCount()">
<b data-bind="text: attachmentsCount"></b> <b data-bind="text: attachmentsCount"></b>
@ -182,13 +182,16 @@
</div> </div>
<div class="pull-right" style="margin-right: 4px;"> <div class="pull-right" style="margin-right: 4px;">
<div class="btn-group pull-right"> <div class="btn-group pull-right">
<a class="btn" data-tooltip-placement="top" data-bind="visible: addAttachmentEnabled(), initDom: composeUploaderButton, tooltip: 'COMPOSE/ATTACH_FILES'"> <a class="btn first" data-tooltip-placement="top"
data-bind="visible: addAttachmentEnabled(), initDom: composeUploaderButton, tooltip: 'COMPOSE/ATTACH_FILES'">
<i class="icon-attachment"></i> <i class="icon-attachment"></i>
</a> </a>
<a class="btn" data-tooltip-placement="top" data-bind="visible: dropboxEnabled, command: dropboxCommand, tooltip: 'COMPOSE/DROPBOX'"> <a class="btn" data-tooltip-placement="top"
data-bind="visible: dropboxEnabled, command: dropboxCommand, tooltip: 'COMPOSE/DROPBOX', css: {'first': !addAttachmentEnabled(), 'last': !driveEnabled()}">
<i class="icon-dropbox"></i> <i class="icon-dropbox"></i>
</a> </a>
<a class="btn" data-tooltip-placement="top" data-bind="visible: driveEnabled() && driveVisible(), command: driveCommand, tooltip: 'COMPOSE/GOOGLE_DRIVE'"> <a class="btn last" data-tooltip-placement="top"
data-bind="visible: driveEnabled() && driveVisible(), command: driveCommand, tooltip: 'COMPOSE/GOOGLE_DRIVE'">
<i class="icon-google-drive"></i> <i class="icon-google-drive"></i>
</a> </a>
</div> </div>

View file

@ -7,7 +7,7 @@
<div class="btn-toolbar"> <div class="btn-toolbar">
<div class="btn-group"> <div class="btn-group">
<a class="btn button-create-contact" data-bind="command: newCommand"> <a class="btn single button-create-contact" data-bind="command: newCommand">
<i class="icon-plus"></i> <i class="icon-plus"></i>
&nbsp;&nbsp; &nbsp;&nbsp;
<span class="i18n" data-i18n-text="CONTACTS/BUTTON_ADD_CONTACT"></span> <span class="i18n" data-i18n-text="CONTACTS/BUTTON_ADD_CONTACT"></span>
@ -15,20 +15,20 @@
</div> </div>
<div class="btn-group"> <div class="btn-group">
<a class="btn btn-success button-new-message" data-bind="command: newMessageCommand"> <a class="btn single btn-success button-new-message" data-bind="command: newMessageCommand">
<i class="icon-mail icon-white"></i> <i class="icon-mail icon-white"></i>
</a> </a>
</div> </div>
<div class="btn-group"> <div class="btn-group">
<a class="btn button-delete" data-bind="command: deleteCommand"> <a class="btn single button-delete" data-bind="command: deleteCommand">
<i class="icon-trash"></i> <i class="icon-trash"></i>
<span data-bind="text: 1 < contactsCheckedOrSelected().length ? ' (' + contactsCheckedOrSelected().length + ')' : ''"></span> <span data-bind="text: 1 < contactsCheckedOrSelected().length ? ' (' + contactsCheckedOrSelected().length + ')' : ''"></span>
</a> </a>
</div> </div>
<div class="btn-group dropdown colored-toggle" data-bind="registrateBootstrapDropdown: true"> <div class="btn-group dropdown colored-toggle" data-bind="registrateBootstrapDropdown: true">
<a id="contacts-more-dropdown-id" class="btn dropdown-toggle buttonMore" href="#" tabindex="-1" data-toggle="dropdown"> <a id="contacts-more-dropdown-id" class="btn single dropdown-toggle buttonMore" href="#" tabindex="-1" data-toggle="dropdown">
<i data-bind="css: {'icon-list': !contacts.importing() && !contacts.syncing(), <i data-bind="css: {'icon-list': !contacts.importing() && !contacts.syncing(),
'icon-spinner animated': contacts.importing() || contacts.syncing()}"></i> 'icon-spinner animated': contacts.importing() || contacts.syncing()}"></i>
</a> </a>
@ -118,7 +118,7 @@
</div> </div>
<div class="b-view-content-toolbar btn-toolbar" data-bind="css: {'read-only': viewReadOnly}"> <div class="b-view-content-toolbar btn-toolbar" data-bind="css: {'read-only': viewReadOnly}">
<div class="btn-group pull-right dropdown colored-toggle button-add-prop" data-bind="visible: !emptySelection(), registrateBootstrapDropdown: true"> <div class="btn-group pull-right dropdown colored-toggle button-add-prop" data-bind="visible: !emptySelection(), registrateBootstrapDropdown: true">
<a id="button-add-prop-dropdown-id" href="#" tabindex="-1" class="btn dropdown-toggle" data-toggle="dropdown"> <a id="button-add-prop-dropdown-id" href="#" tabindex="-1" class="btn single dropdown-toggle" data-toggle="dropdown">
<span class="i18n" data-i18n-text="CONTACTS/ADD_MENU_LABEL"></span> <span class="i18n" data-i18n-text="CONTACTS/ADD_MENU_LABEL"></span>
&nbsp;&nbsp; &nbsp;&nbsp;
<span class="caret"></span> <span class="caret"></span>
@ -162,7 +162,7 @@
</div> </div>
<div class="btn-group pull-right">&nbsp;</div> <div class="btn-group pull-right">&nbsp;</div>
<div class="btn-group pull-right"> <div class="btn-group pull-right">
<button class="btn button-save-contact" data-bind="visible: !emptySelection(), command: saveCommand, css: {'dirty': watchDirty}"> <button class="btn single button-save-contact" data-bind="visible: !emptySelection(), command: saveCommand, css: {'dirty': watchDirty}">
<i data-bind="css: {'icon-ok': !viewSaving(), 'icon-spinner animated': viewSaving()}"></i> <i data-bind="css: {'icon-ok': !viewSaving(), 'icon-spinner animated': viewSaving()}"></i>
&nbsp;&nbsp; &nbsp;&nbsp;
<span class="i18n" data-i18n-text="CONTACTS/BUTTON_CREATE_CONTACT" data-bind="visible: '' === viewID()"></span> <span class="i18n" data-i18n-text="CONTACTS/BUTTON_CREATE_CONTACT" data-bind="visible: '' === viewID()"></span>

View file

@ -18,7 +18,7 @@
<nobr> <nobr>
<div class="btn-toolbar"> <div class="btn-toolbar">
<div class="btn-group"> <div class="btn-group">
<a class="btn buttonResize" data-bind="click: function () { leftPanelDisabled(!leftPanelDisabled()); }"> <a class="btn single buttonResize" data-bind="click: function () { leftPanelDisabled(!leftPanelDisabled()); }">
<i data-bind="css: {'icon-resize-out': leftPanelDisabled(), 'icon-resize-in': !leftPanelDisabled()}"></i> <i data-bind="css: {'icon-resize-out': leftPanelDisabled(), 'icon-resize-in': !leftPanelDisabled()}"></i>
</a> </a>
</div> </div>

View file

@ -2,7 +2,7 @@
<div class="b-toolbar"> <div class="b-toolbar">
<div class="btn-toolbar"> <div class="btn-toolbar">
<div class="btn-group pull-right dropdown colored-toggle" data-bind="registrateBootstrapDropdown: true, openDropdownTrigger: accountMenuDropdownTrigger"> <div class="btn-group pull-right dropdown colored-toggle" data-bind="registrateBootstrapDropdown: true, openDropdownTrigger: accountMenuDropdownTrigger">
<a id="top-system-dropdown-id" href="#" tabindex="-1" class="btn btn-ellipsis btn-block dropdown-toggle system-dropdown" data-toggle="dropdown"> <a id="top-system-dropdown-id" href="#" tabindex="-1" class="btn single btn-ellipsis btn-block dropdown-toggle system-dropdown" data-toggle="dropdown">
<i data-bind="css: {'icon-user': !accounts.loading(), 'icon-spinner animated': accounts.loading()}" <i data-bind="css: {'icon-user': !accounts.loading(), 'icon-spinner animated': accounts.loading()}"
></i> ></i>
<!-- <!--