Message thread optimization

This commit is contained in:
RainLoop Team 2015-04-15 02:27:10 +04:00
parent 0c145a054a
commit a4904f4c00
7 changed files with 140 additions and 53 deletions

View file

@ -153,7 +153,20 @@
Cache.initMessageFlagsFromCache(oMessage); Cache.initMessageFlagsFromCache(oMessage);
}); });
_.each(MessageStore.messageThreadList(), function (oMessage) {
Cache.initMessageFlagsFromCache(oMessage);
});
Cache.initMessageFlagsFromCache(MessageStore.message()); Cache.initMessageFlagsFromCache(MessageStore.message());
this.reloadFlagsCurrentMessageThreadListFromCache();
};
AppUser.prototype.reloadFlagsCurrentMessageThreadListFromCache = function ()
{
_.each(MessageStore.messageThreadList(), function (oMessage) {
Cache.initMessageFlagsFromCache(oMessage);
});
}; };
/** /**
@ -860,19 +873,21 @@
bRoot = true; bRoot = true;
} }
else if (aMessages && aMessages[0] && mUid && else if (aMessages && aMessages[0] && mUid &&
sFolderFullNameRaw === aMessages[0].uid && mUid === aMessages[0].uid) sFolderFullNameRaw === aMessages[0].folderFullNameRaw && mUid === aMessages[0].uid)
{ {
bRoot = true; bRoot = true;
} }
_.each(aMessages, function (oMessage) { _.each(aMessages, function (oMessage) {
aRootUids.push(oMessage.uid); if (oMessage && oMessage.uid && oMessage.threads)
aAllUids = _.union(aAllUids, oMessage.threads(), [oMessage.uid]); {
aRootUids.push(oMessage.uid);
aAllUids = _.union(aAllUids, oMessage.threads(), [oMessage.uid]);
}
}); });
aAllUids = _.uniq(aAllUids); aAllUids = _.uniq(aAllUids);
aRootUids = _.uniq(aRootUids); aRootUids = _.uniq(aRootUids);
aRootUids = aAllUids; // always all
if ('' !== sFolderFullNameRaw && 0 < aAllUids.length) if ('' !== sFolderFullNameRaw && 0 < aAllUids.length)
{ {
@ -921,12 +936,14 @@
case Enums.MessageSetAction.UnsetFlag: case Enums.MessageSetAction.UnsetFlag:
_.each(bRoot ? aAllUids : aRootUids, function (sSubUid) { _.each(aRootUids, function (sSubUid) {
// _.each(bRoot ? aAllUids : aRootUids, function (sSubUid) {
Cache.storeMessageFlagsToCacheBySetAction( Cache.storeMessageFlagsToCacheBySetAction(
sFolderFullNameRaw, sSubUid, iSetAction); sFolderFullNameRaw, sSubUid, iSetAction);
}); });
Remote.messageSetFlagged(Utils.emptyFunction, sFolderFullNameRaw, bRoot ? aAllUids : aRootUids, false); Remote.messageSetFlagged(Utils.emptyFunction, sFolderFullNameRaw, aRootUids, false);
// Remote.messageSetFlagged(Utils.emptyFunction, sFolderFullNameRaw, bRoot ? aAllUids : aRootUids, false);
break; break;
} }

View file

@ -302,12 +302,16 @@
if (aFlags && 0 < aFlags.length) if (aFlags && 0 < aFlags.length)
{ {
oMessage.unseen(!!aFlags[0]);
oMessage.flagged(!!aFlags[1]); oMessage.flagged(!!aFlags[1]);
oMessage.answered(!!aFlags[2]);
oMessage.forwarded(!!aFlags[3]); if (!oMessage.__simple_message__)
oMessage.isReadReceipt(!!aFlags[4]); {
oMessage.deletedMark(!!aFlags[5]); oMessage.unseen(!!aFlags[0]);
oMessage.answered(!!aFlags[2]);
oMessage.forwarded(!!aFlags[3]);
oMessage.isReadReceipt(!!aFlags[4]);
oMessage.deletedMark(!!aFlags[5]);
}
} }
if (0 < oMessage.threads().length) if (0 < oMessage.threads().length)

View file

@ -5,6 +5,7 @@
var var
_ = require('_'), _ = require('_'),
ko = require('ko'),
Utils = require('Common/Utils'), Utils = require('Common/Utils'),
@ -20,11 +21,18 @@
function MessageSimpleModel(sSuperName) function MessageSimpleModel(sSuperName)
{ {
AbstractModel.call(this, sSuperName || 'MessageSimpleModel'); AbstractModel.call(this, sSuperName || 'MessageSimpleModel');
this.flagged = ko.observable(false);
this.selected = ko.observable(false);
} }
_.extend(MessageSimpleModel.prototype, AbstractModel.prototype); _.extend(MessageSimpleModel.prototype, AbstractModel.prototype);
MessageSimpleModel.prototype.__simple_message__ = true;
MessageSimpleModel.prototype.folder = ''; MessageSimpleModel.prototype.folder = '';
MessageSimpleModel.prototype.folderFullNameRaw = '';
MessageSimpleModel.prototype.uid = ''; MessageSimpleModel.prototype.uid = '';
MessageSimpleModel.prototype.subject = ''; MessageSimpleModel.prototype.subject = '';
@ -48,6 +56,8 @@
MessageSimpleModel.prototype.clear = function () MessageSimpleModel.prototype.clear = function ()
{ {
this.folder = ''; this.folder = '';
this.folderFullNameRaw = '';
this.uid = ''; this.uid = '';
this.subject = ''; this.subject = '';
@ -68,6 +78,9 @@
this.size = 0; this.size = 0;
this.timestamp = 0; this.timestamp = 0;
this.flagged(false);
this.selected(false);
}; };
/** /**
@ -81,6 +94,8 @@
if (oJson && 'Object/Message' === oJson['@Object']) if (oJson && 'Object/Message' === oJson['@Object'])
{ {
this.folder = Utils.pString(oJson.Folder); this.folder = Utils.pString(oJson.Folder);
this.folderFullNameRaw = this.folder;
this.uid = Utils.pString(oJson.Uid); this.uid = Utils.pString(oJson.Uid);
this.subject = Utils.pString(oJson.Subject); this.subject = Utils.pString(oJson.Subject);
@ -112,6 +127,9 @@
this.toAsString = MessageHelper.emailArrayToString(this.to, true); this.toAsString = MessageHelper.emailArrayToString(this.to, true);
this.toAsStringClear = MessageHelper.emailArrayToStringClear(this.to); this.toAsStringClear = MessageHelper.emailArrayToStringClear(this.to);
this.flagged(false);
this.selected(false);
this.populateSenderEmail(); this.populateSenderEmail();
bResult = true; bResult = true;
@ -132,6 +150,14 @@
} }
}; };
/**
* @return {Array}
*/
MessageSimpleModel.prototype.threads = function ()
{
return [];
};
/** /**
* @static * @static
* @param {Object} oJson * @param {Object} oJson

View file

@ -63,6 +63,8 @@
this.message.viewTrigger = ko.observable(false); this.message.viewTrigger = ko.observable(false);
this.messageThreadList = ko.observableArray([]);
this.messageLastThreadUidsData = ko.observable(null); this.messageLastThreadUidsData = ko.observable(null);
this.messageError = ko.observable(''); this.messageError = ko.observable('');

View file

@ -76,6 +76,23 @@ html.rl-no-preview-pane {
right: 10px; right: 10px;
} }
.flagParent {
cursor: pointer;
margin-right: 5px;
.flagOn {
color: orange;
}
.flagOff {
opacity: 0.5;
&:hover {
opacity: 1;
}
}
}
.messageItemHeader { .messageItemHeader {
position: absolute; position: absolute;
@ -120,23 +137,6 @@ html.rl-no-preview-pane {
margin-top: 5px; margin-top: 5px;
} }
.flagParent {
cursor: pointer;
margin-right: 5px;
.flagOn {
color: orange;
}
.flagOff {
opacity: 0.5;
&:hover {
opacity: 1;
}
}
}
.informationShort { .informationShort {
margin-left: 22px; margin-left: 22px;
a { a {

View file

@ -56,6 +56,7 @@
} }
; ;
this.oDom = null;
this.oHeaderDom = null; this.oHeaderDom = null;
this.oMessageScrollerDom = null; this.oMessageScrollerDom = null;
@ -232,14 +233,38 @@
this.viewThreads = ko.observableArray([]); this.viewThreads = ko.observableArray([]);
this.viewThreads.trigger = ko.observable(false); this.viewThreads.trigger = ko.observable(false);
this.viewThreadMessages = ko.observableArray([]); this.viewThreadMessages = MessageStore.messageThreadList;
this.viewThreadMessages.error = ko.observable(''); this.viewThreadMessages.error = ko.observable('');
this.viewThreadMessages.showMore = ko.observable(false); this.viewThreadMessages.showMore = ko.observable(false);
this.viewThreadMessages.limit = 6; this.viewThreadMessages.limit = 6;
this.viewThreadMessages.subscribe(function (aList) { this.viewThreadMessages.subscribe(function (aList) {
var iSelectedIndex = -1;
this.viewThreadMessages.error(''); this.viewThreadMessages.error('');
this.viewThreadMessages.showMore(this.viewThreadMessages.limit >= aList.length); if (aList && 0 < aList.length)
{
_.each(aList, function (oM, iIndex) {
if (oM && oM.selected())
{
iSelectedIndex = iIndex;
}
});
this.viewThreadMessages.showMore(this.viewThreadMessages.limit >= aList.length);
if (-1 < iSelectedIndex && !this.viewThreadMessages.showMore() &&
this.viewThreadMessages.limit < iSelectedIndex)
{
this.viewThreadMessages.showMore(true);
}
this.selectSelectedThreadMessage();
require('App/User').reloadFlagsCurrentMessageListAndMessageFromCache();
}
}, this); }, this);
MessageStore.messageLastThreadUidsData.subscribe(function (oData) { MessageStore.messageLastThreadUidsData.subscribe(function (oData) {
@ -344,7 +369,7 @@
_.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);
} }
}); });
@ -530,15 +555,6 @@
kn.extendAsViewModel(['View/User/MailBox/MessageView', 'View/App/MailBox/MessageView', 'MailBoxMessageViewViewModel'], MessageViewMailBoxUserView); kn.extendAsViewModel(['View/User/MailBox/MessageView', 'View/App/MailBox/MessageView', 'MailBoxMessageViewViewModel'], MessageViewMailBoxUserView);
_.extend(MessageViewMailBoxUserView.prototype, AbstractView.prototype); _.extend(MessageViewMailBoxUserView.prototype, AbstractView.prototype);
MessageViewMailBoxUserView.prototype.updateViewFlagsFromCache = function ()
{
var aFlags = this.getMessageFlagsFromCache(this.viewFolder, this.viewUid);
if (aFlags)
{
this.viewIsFlagged(!!aFlags[1]);
}
};
MessageViewMailBoxUserView.prototype.openThreadMessage = function (sUid) MessageViewMailBoxUserView.prototype.openThreadMessage = function (sUid)
{ {
var oMessage = this.message(); var oMessage = this.message();
@ -635,6 +651,8 @@
fCheckHeaderHeight = _.bind(this.checkHeaderHeight, this) fCheckHeaderHeight = _.bind(this.checkHeaderHeight, this)
; ;
this.oDom = oDom;
this.fullScreenMode.subscribe(function (bValue) { this.fullScreenMode.subscribe(function (bValue) {
if (bValue && self.message()) if (bValue && self.message())
{ {
@ -785,7 +803,7 @@
self.viewThreadMessages.showMore(true); self.viewThreadMessages.showMore(true);
self.threadsDropdownTrigger(true); self.threadsDropdownTrigger(true);
if (oLast) if (oLast && oLast[0])
{ {
oLast.focus(); oLast.focus();
} }
@ -810,8 +828,26 @@
require('App/User').download(oAttachment.linkDownload()); require('App/User').download(oAttachment.linkDownload());
} }
}) })
.on('click', '.messageItemHeader .flagParent', function () { .on('click', '.messageItemHeader .subjectParent .flagParent', function () {
self.flagViewMessage(); var oMessage = self.message();
if (oMessage)
{
require('App/User').messageListAction(oMessage.folderFullNameRaw, oMessage.uid,
oMessage.flagged() ? Enums.MessageSetAction.UnsetFlag : Enums.MessageSetAction.SetFlag, [oMessage]);
}
})
.on('click', '.thread-list .flagParent', function () {
var oMessage = ko.dataFor(this);
if (oMessage && oMessage.folder && oMessage.uid)
{
require('App/User').messageListAction(
oMessage.folder, oMessage.uid,
oMessage.flagged() ? Enums.MessageSetAction.UnsetFlag : Enums.MessageSetAction.SetFlag, [oMessage]);
}
self.threadsDropdownTrigger(true);
return false;
}) })
; ;
@ -833,17 +869,16 @@
this.initShortcuts(); this.initShortcuts();
}; };
/** MessageViewMailBoxUserView.prototype.selectSelectedThreadMessage = function ()
* @return {boolean}
*/
MessageViewMailBoxUserView.prototype.flagViewMessage = function ()
{ {
var oMessage = this.message(); var self = this;
if (oMessage) _.delay(function () {
{ var oLast = self.oDom ? $('.thread-list .e-item.thread-list-message.real-msg.selected a.e-link', self.oDom) : null;
require('App/User').messageListAction(oMessage.folderFullNameRaw, oMessage.uid, if (oLast && oLast[0])
oMessage.flagged() ? Enums.MessageSetAction.UnsetFlag : Enums.MessageSetAction.SetFlag, [oMessage]); {
} oLast.focus();
}
}, 30);
}; };
/** /**

View file

@ -219,6 +219,9 @@
<div data-bind="foreach: viewThreadMessages, visible: !messageListOfThreadsLoading()"> <div data-bind="foreach: viewThreadMessages, visible: !messageListOfThreadsLoading()">
<li class="e-item thread-list-message real-msg" role="presentation" data-bind="css: {'selected': selected, 'more-that': $parent.viewThreadMessages.limit < $index() }"> <li class="e-item thread-list-message real-msg" role="presentation" data-bind="css: {'selected': selected, 'more-that': $parent.viewThreadMessages.limit < $index() }">
<a class="e-link menuitem" href="#" tabindex="-1" onclick="return false;"> <a class="e-link menuitem" href="#" tabindex="-1" onclick="return false;">
<span class="flagParent pull-right" style="margin-left: 5px; margin-right: 0px;">
<i class="icon-star-empty flagOff" data-bind="css: {'icon-star flagOn': flagged, 'icon-star-empty flagOff': !flagged()}"></i>
</span>
<span class="thread-date pull-right" data-moment-format="SHORT" data-bind="moment: timestamp"></span> <span class="thread-date pull-right" data-moment-format="SHORT" data-bind="moment: timestamp"></span>
<div style="text-overflow: ellipsis; overflow: hidden;"> <div style="text-overflow: ellipsis; overflow: hidden;">
<span class="thread-from" data-bind="text: fromAsString"></span> <span class="thread-from" data-bind="text: fromAsString"></span>