mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-07-13 03:27:39 +03:00
Message thread optimization
This commit is contained in:
parent
0c145a054a
commit
a4904f4c00
7 changed files with 140 additions and 53 deletions
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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('');
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue