Smooth reload animation

This commit is contained in:
RainLoop Team 2015-03-31 04:12:05 +04:00
parent de06ab1a41
commit 18931eaca0
6 changed files with 97 additions and 16 deletions

50
dev/External/ko.js vendored
View file

@ -938,23 +938,59 @@
ko.extenders.falseTimeout = function (oTarget, iOption) ko.extenders.falseTimeout = function (oTarget, iOption)
{ {
var Utils = require('Common/Utils'); oTarget.iFalseTimeoutTimeout = 0;
oTarget.iTimeout = 0;
oTarget.subscribe(function (bValue) { oTarget.subscribe(function (bValue) {
if (bValue) if (bValue)
{ {
window.clearTimeout(oTarget.iTimeout); window.clearTimeout(oTarget.iFalseTimeoutTimeout);
oTarget.iTimeout = window.setTimeout(function () { oTarget.iFalseTimeoutTimeout = window.setTimeout(function () {
oTarget(false); oTarget(false);
oTarget.iTimeout = 0; oTarget.iFalseTimeoutTimeout = 0;
}, Utils.pInt(iOption)); }, require('Common/Utils').pInt(iOption));
} }
}); });
return oTarget; return oTarget;
}; };
ko.extenders.specialThrottle = function (oTarget, iOption)
{
oTarget.iSpecialThrottleTimeoutValue = require('Common/Utils').pInt(iOption);
if (0 < oTarget.iSpecialThrottleTimeoutValue)
{
oTarget.iSpecialThrottleTimeout = 0;
oTarget.valueForRead = ko.observable(!!oTarget()).extend({'throttle': 10});
return ko.computed({
'read': oTarget.valueForRead,
'write': function (bValue) {
if (bValue)
{
oTarget.valueForRead(bValue);
}
else
{
if (oTarget.valueForRead())
{
window.clearTimeout(oTarget.iSpecialThrottleTimeout);
oTarget.iSpecialThrottleTimeout = window.setTimeout(function () {
oTarget.valueForRead(false);
oTarget.iSpecialThrottleTimeout = 0;
}, oTarget.iSpecialThrottleTimeoutValue);
}
else
{
oTarget.valueForRead(bValue);
}
}
}
});
}
return oTarget;
};
// functions // functions
ko.observable.fn.validateNone = function () ko.observable.fn.validateNone = function ()

View file

@ -662,9 +662,10 @@
/** /**
* @param {Object} oExcludeEmails * @param {Object} oExcludeEmails
* @param {boolean=} bLast = false
* @return {Array} * @return {Array}
*/ */
MessageModel.prototype.replyEmails = function (oExcludeEmails) MessageModel.prototype.replyEmails = function (oExcludeEmails, bLast)
{ {
var var
aResult = [], aResult = [],
@ -677,16 +678,23 @@
MessageHelper.replyHelper(this.from, oUnic, aResult); MessageHelper.replyHelper(this.from, oUnic, aResult);
} }
if (0 === aResult.length && !bLast)
{
return this.replyEmails({}, true);
}
return aResult; return aResult;
}; };
/** /**
* @param {Object} oExcludeEmails * @param {Object} oExcludeEmails
* @param {boolean=} bLast = false
* @return {Array.<Array>} * @return {Array.<Array>}
*/ */
MessageModel.prototype.replyAllEmails = function (oExcludeEmails) MessageModel.prototype.replyAllEmails = function (oExcludeEmails, bLast)
{ {
var var
aData = [],
aToResult = [], aToResult = [],
aCcResult = [], aCcResult = [],
oUnic = Utils.isUnd(oExcludeEmails) ? {} : oExcludeEmails oUnic = Utils.isUnd(oExcludeEmails) ? {} : oExcludeEmails
@ -701,6 +709,12 @@
MessageHelper.replyHelper(this.to, oUnic, aToResult); MessageHelper.replyHelper(this.to, oUnic, aToResult);
MessageHelper.replyHelper(this.cc, oUnic, aCcResult); MessageHelper.replyHelper(this.cc, oUnic, aCcResult);
if (0 === aToResult.length && !bLast)
{
aData = this.replyAllEmails({}, true);
return [aData[0], aCcResult];
}
return [aToResult, aCcResult]; return [aToResult, aCcResult];
}; };

View file

@ -51,6 +51,7 @@
this.messageListLoading = ko.observable(false); this.messageListLoading = ko.observable(false);
this.messageListIsNotCompleted = ko.observable(false); this.messageListIsNotCompleted = ko.observable(false);
this.messageListCompleteLoadingThrottle = ko.observable(false).extend({'throttle': 200}); this.messageListCompleteLoadingThrottle = ko.observable(false).extend({'throttle': 200});
this.messageListCompleteLoadingThrottleForAnimation = ko.observable(false).extend({'specialThrottle': 700});
this.messageListDisableAutoSelect = ko.observable(false).extend({'falseTimeout': 500}); this.messageListDisableAutoSelect = ko.observable(false).extend({'falseTimeout': 500});
@ -164,7 +165,9 @@
MessageUserStore.prototype.subscribers = function () MessageUserStore.prototype.subscribers = function ()
{ {
this.messageListCompleteLoading.subscribe(function (bValue) { this.messageListCompleteLoading.subscribe(function (bValue) {
bValue = !!bValue;
this.messageListCompleteLoadingThrottle(bValue); this.messageListCompleteLoadingThrottle(bValue);
this.messageListCompleteLoadingThrottleForAnimation(bValue);
}, this); }, this);
this.messageList.subscribe(_.debounce(function (aList) { this.messageList.subscribe(_.debounce(function (aList) {

View file

@ -9,6 +9,10 @@
0% { transform: scale(1); } 50% { transform: scale(1.1); } 100% { transform: scale(1); } 0% { transform: scale(1); } 50% { transform: scale(1.1); } 100% { transform: scale(1); }
} }
@keyframes bounce-me {
0% { transform: scale(1); } 50% { transform: scale(1.1); } 100% { transform: scale(1); }
}
@keyframes textLoadingAnimationKeyFrame { @keyframes textLoadingAnimationKeyFrame {
0% { opacity: 1; } 33% { opacity: 0; } 100% { opacity: 1; } 0% { opacity: 1; } 33% { opacity: 0; } 100% { opacity: 1; }
} }
@ -56,6 +60,10 @@ html.csstransitions.rl-started-trigger.no-mobile .b-login-content .loginFormWrap
.transition(opacity 0.3s ease-out); .transition(opacity 0.3s ease-out);
}*/ }*/
&.csstransitions.no-mobile .btn-group.dropdown.colored-toggle.open .animate-this-icon-on-open {
animation: bounce-me .5s linear;
}
&.csstransitions.no-mobile .b-login-content .loginFormWrapper { &.csstransitions.no-mobile .b-login-content .loginFormWrapper {
.transition(all 0.3s ease-out); .transition(all 0.3s ease-out);
} }

View file

@ -70,6 +70,7 @@
this.messageListCheckedOrSelected = MessageStore.messageListCheckedOrSelected; this.messageListCheckedOrSelected = MessageStore.messageListCheckedOrSelected;
this.messageListCheckedOrSelectedUidsWithSubMails = MessageStore.messageListCheckedOrSelectedUidsWithSubMails; this.messageListCheckedOrSelectedUidsWithSubMails = MessageStore.messageListCheckedOrSelectedUidsWithSubMails;
this.messageListCompleteLoadingThrottle = MessageStore.messageListCompleteLoadingThrottle; this.messageListCompleteLoadingThrottle = MessageStore.messageListCompleteLoadingThrottle;
this.messageListCompleteLoadingThrottleForAnimation = MessageStore.messageListCompleteLoadingThrottleForAnimation;
Translator.initOnStartOrLangChange(function () { Translator.initOnStartOrLangChange(function () {
this.emptySubjectValue = Translator.i18n('MESSAGE_LIST/EMPTY_SUBJECT_TEXT'); this.emptySubjectValue = Translator.i18n('MESSAGE_LIST/EMPTY_SUBJECT_TEXT');
@ -174,6 +175,18 @@
return Consts.Values.UnuseOptionValue === FolderStore.archiveFolder(); return Consts.Values.UnuseOptionValue === FolderStore.archiveFolder();
}, this); }, this);
this.isArchiveVisible = ko.computed(function () {
return !this.isArchiveFolder() && !this.isArchiveDisabled() && !this.isDraftFolder();
}, this);
this.isSpamVisible = ko.computed(function () {
return !this.isSpamFolder() && !this.isSpamDisabled() && !this.isDraftFolder() && !this.isSentFolder();
}, this);
this.isUnSpamVisible = ko.computed(function () {
return this.isSpamFolder() && !this.isSpamDisabled() && !this.isDraftFolder() && !this.isSentFolder();
}, this);
this.canBeMoved = this.hasCheckedOrSelectedLines; this.canBeMoved = this.hasCheckedOrSelectedLines;
this.clearCommand = Utils.createCommand(this, function () { this.clearCommand = Utils.createCommand(this, function () {
@ -218,7 +231,7 @@
this.moveCommand = Utils.createCommand(this, Utils.emptyFunction, this.canBeMoved); this.moveCommand = Utils.createCommand(this, Utils.emptyFunction, this.canBeMoved);
this.reloadCommand = Utils.createCommand(this, function () { this.reloadCommand = Utils.createCommand(this, function () {
if (!MessageStore.messageListCompleteLoadingThrottle()) if (!MessageStore.messageListCompleteLoadingThrottleForAnimation())
{ {
require('App/User').reloadMessageList(false, true); require('App/User').reloadMessageList(false, true);
} }

View file

@ -5,7 +5,7 @@
<div class="btn-toolbar"> <div class="btn-toolbar">
<div class="btn-group"> <div class="btn-group">
<a class="btn single 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': messageListCompleteLoadingThrottleForAnimation}"></i>
</a> </a>
</div> </div>
<div class="btn-group">&nbsp;</div> <div class="btn-group">&nbsp;</div>
@ -29,16 +29,23 @@
</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 first 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: isArchiveVisible, 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: isSpamVisible, command: spamCommand, tooltip: 'MESSAGE_LIST/BUTTON_SPAM',
css: {'first': !isArchiveVisible()}">
<i class="icon-angry-smiley"></i> <i class="icon-angry-smiley"></i>
</a> </a>
<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: isUnSpamVisible, command: notSpamCommand, tooltip: 'MESSAGE_LIST/BUTTON_NOT_SPAM',
css: {'first': !isArchiveVisible()}">
<i class="icon-happy-smiley"></i> <i class="icon-happy-smiley"></i>
</a> </a>
<a class="btn last 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',
css: {'first': !isArchiveVisible() && !isSpamVisible() && !isUnSpamVisible()}">
<i class="icon-trash"></i> <i class="icon-trash"></i>
<!--<span data-bind="text: printableMessageCountForDeletion()"></span>--> <!--<span data-bind="text: printableMessageCountForDeletion()"></span>-->
</a> </a>
@ -46,7 +53,7 @@
<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 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'"> <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 animate-this-icon-on-open"></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">
<li class="e-item" role="presentation" data-bind="click: listUnsetSeen, css: {'disabled': !hasCheckedOrSelectedLines()}"> <li class="e-item" role="presentation" data-bind="click: listUnsetSeen, css: {'disabled': !hasCheckedOrSelectedLines()}">