mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-07-13 03:27:39 +03:00
New thread controller
This commit is contained in:
parent
9dbf77f942
commit
b6ca9e357e
20 changed files with 922 additions and 595 deletions
101
dev/App/User.js
101
dev/App/User.js
|
|
@ -831,24 +831,105 @@
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
AppUser.prototype.setMessageSeen = function (oMessage)
|
/**
|
||||||
|
* @param {string} sFolderFullNameRaw
|
||||||
|
* @param {string|bool} mUid
|
||||||
|
* @param {number} iSetAction
|
||||||
|
* @param {Array=} aMessages = null
|
||||||
|
*/
|
||||||
|
AppUser.prototype.messageListAction = function (sFolderFullNameRaw, mUid, iSetAction, aMessages)
|
||||||
{
|
{
|
||||||
if (oMessage.unseen())
|
var
|
||||||
{
|
bRoot = false,
|
||||||
oMessage.unseen(false);
|
aAllUids = [],
|
||||||
|
aRootUids = [],
|
||||||
|
oFolder = null,
|
||||||
|
iAlreadyUnread = 0
|
||||||
|
;
|
||||||
|
|
||||||
var oFolder = Cache.getFolderFromCacheList(oMessage.folderFullNameRaw);
|
if (Utils.isUnd(aMessages))
|
||||||
|
{
|
||||||
|
aMessages = MessageStore.messageListChecked();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (true === mUid)
|
||||||
|
{
|
||||||
|
bRoot = true;
|
||||||
|
}
|
||||||
|
else if (aMessages && aMessages[0] && mUid &&
|
||||||
|
sFolderFullNameRaw === aMessages[0].uid && mUid === aMessages[0].uid)
|
||||||
|
{
|
||||||
|
bRoot = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
_.each(aMessages, function (oMessage) {
|
||||||
|
aRootUids.push(oMessage.uid);
|
||||||
|
aAllUids = _.union(aAllUids, oMessage.threads(), [oMessage.uid]);
|
||||||
|
});
|
||||||
|
|
||||||
|
aAllUids = _.uniq(aAllUids);
|
||||||
|
aRootUids = _.uniq(aRootUids);
|
||||||
|
aRootUids = aAllUids; // always all
|
||||||
|
|
||||||
|
if ('' !== sFolderFullNameRaw && 0 < aAllUids.length)
|
||||||
|
{
|
||||||
|
switch (iSetAction) {
|
||||||
|
case Enums.MessageSetAction.SetSeen:
|
||||||
|
|
||||||
|
_.each(bRoot ? aAllUids : aRootUids, function (sSubUid) {
|
||||||
|
iAlreadyUnread += Cache.storeMessageFlagsToCacheBySetAction(
|
||||||
|
sFolderFullNameRaw, sSubUid, iSetAction);
|
||||||
|
});
|
||||||
|
|
||||||
|
oFolder = Cache.getFolderFromCacheList(sFolderFullNameRaw);
|
||||||
if (oFolder)
|
if (oFolder)
|
||||||
{
|
{
|
||||||
oFolder.messageCountUnread(0 <= oFolder.messageCountUnread() - 1 ?
|
oFolder.messageCountUnread(oFolder.messageCountUnread() - iAlreadyUnread);
|
||||||
oFolder.messageCountUnread() - 1 : 0);
|
}
|
||||||
|
|
||||||
|
Remote.messageSetSeen(Utils.emptyFunction, sFolderFullNameRaw, bRoot ? aAllUids : aRootUids, true);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Enums.MessageSetAction.UnsetSeen:
|
||||||
|
|
||||||
|
_.each(aRootUids, function (sSubUid) {
|
||||||
|
iAlreadyUnread += Cache.storeMessageFlagsToCacheBySetAction(
|
||||||
|
sFolderFullNameRaw, sSubUid, iSetAction);
|
||||||
|
});
|
||||||
|
|
||||||
|
oFolder = Cache.getFolderFromCacheList(sFolderFullNameRaw);
|
||||||
|
if (oFolder)
|
||||||
|
{
|
||||||
|
oFolder.messageCountUnread(oFolder.messageCountUnread() - iAlreadyUnread + aRootUids.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
Remote.messageSetSeen(Utils.emptyFunction, sFolderFullNameRaw, aRootUids, false);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Enums.MessageSetAction.SetFlag:
|
||||||
|
|
||||||
|
_.each(aRootUids, function (sSubUid) {
|
||||||
|
Cache.storeMessageFlagsToCacheBySetAction(
|
||||||
|
sFolderFullNameRaw, sSubUid, iSetAction);
|
||||||
|
});
|
||||||
|
|
||||||
|
Remote.messageSetFlagged(Utils.emptyFunction, sFolderFullNameRaw, aRootUids, true);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Enums.MessageSetAction.UnsetFlag:
|
||||||
|
|
||||||
|
_.each(bRoot ? aAllUids : aRootUids, function (sSubUid) {
|
||||||
|
Cache.storeMessageFlagsToCacheBySetAction(
|
||||||
|
sFolderFullNameRaw, sSubUid, iSetAction);
|
||||||
|
});
|
||||||
|
|
||||||
|
Remote.messageSetFlagged(Utils.emptyFunction, sFolderFullNameRaw, bRoot ? aAllUids : aRootUids, false);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
Cache.storeMessageFlagsToCache(oMessage);
|
|
||||||
this.reloadFlagsCurrentMessageListAndMessageFromCache();
|
this.reloadFlagsCurrentMessageListAndMessageFromCache();
|
||||||
|
MessageStore.message.viewTrigger(!MessageStore.message.viewTrigger());
|
||||||
}
|
}
|
||||||
|
|
||||||
Remote.messageSetSeen(Utils.emptyFunction, oMessage.folderFullNameRaw, [oMessage.uid], true);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
AppUser.prototype.googleConnect = function ()
|
AppUser.prototype.googleConnect = function ()
|
||||||
|
|
|
||||||
|
|
@ -301,7 +301,8 @@
|
||||||
{
|
{
|
||||||
var
|
var
|
||||||
self = this,
|
self = this,
|
||||||
aFlags = this.getMessageFlagsFromCache(oMessage.folderFullNameRaw, oMessage.uid),
|
sUid = oMessage.uid,
|
||||||
|
aFlags = this.getMessageFlagsFromCache(oMessage.folderFullNameRaw, sUid),
|
||||||
mUnseenSubUid = null,
|
mUnseenSubUid = null,
|
||||||
mFlaggedSubUid = null
|
mFlaggedSubUid = null
|
||||||
;
|
;
|
||||||
|
|
@ -318,13 +319,19 @@
|
||||||
|
|
||||||
if (0 < oMessage.threads().length)
|
if (0 < oMessage.threads().length)
|
||||||
{
|
{
|
||||||
mUnseenSubUid = _.find(oMessage.threads(), function (iSubUid) {
|
mUnseenSubUid = _.find(oMessage.threads(), function (sSubUid) {
|
||||||
var aFlags = self.getMessageFlagsFromCache(oMessage.folderFullNameRaw, iSubUid);
|
if (sUid === sSubUid){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
var aFlags = self.getMessageFlagsFromCache(oMessage.folderFullNameRaw, sSubUid);
|
||||||
return aFlags && 0 < aFlags.length && !!aFlags[0];
|
return aFlags && 0 < aFlags.length && !!aFlags[0];
|
||||||
});
|
});
|
||||||
|
|
||||||
mFlaggedSubUid = _.find(oMessage.threads(), function (iSubUid) {
|
mFlaggedSubUid = _.find(oMessage.threads(), function (sSubUid) {
|
||||||
var aFlags = self.getMessageFlagsFromCache(oMessage.folderFullNameRaw, iSubUid);
|
if (sUid === sSubUid){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
var aFlags = self.getMessageFlagsFromCache(oMessage.folderFullNameRaw, sSubUid);
|
||||||
return aFlags && 0 < aFlags.length && !!aFlags[1];
|
return aFlags && 0 < aFlags.length && !!aFlags[1];
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -349,6 +356,7 @@
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string} sFolder
|
* @param {string} sFolder
|
||||||
* @param {string} sUid
|
* @param {string} sUid
|
||||||
|
|
@ -362,6 +370,43 @@
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} sFolder
|
||||||
|
* @param {string} sUid
|
||||||
|
* @param {number} iSetAction
|
||||||
|
*/
|
||||||
|
CacheUserStorage.prototype.storeMessageFlagsToCacheBySetAction = function (sFolder, sUid, iSetAction)
|
||||||
|
{
|
||||||
|
var iUnread = 0, aFlags = this.getMessageFlagsFromCache(sFolder, sUid);
|
||||||
|
if (Utils.isArray(aFlags) && 0 < aFlags.length)
|
||||||
|
{
|
||||||
|
if (aFlags[0])
|
||||||
|
{
|
||||||
|
iUnread = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (iSetAction)
|
||||||
|
{
|
||||||
|
case Enums.MessageSetAction.SetSeen:
|
||||||
|
aFlags[0] = false;
|
||||||
|
break;
|
||||||
|
case Enums.MessageSetAction.UnsetSeen:
|
||||||
|
aFlags[0] = true;
|
||||||
|
break;
|
||||||
|
case Enums.MessageSetAction.SetFlag:
|
||||||
|
aFlags[1] = true;
|
||||||
|
break;
|
||||||
|
case Enums.MessageSetAction.UnsetFlag:
|
||||||
|
aFlags[1] = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setMessageFlagsToCache(sFolder, sUid, aFlags);
|
||||||
|
}
|
||||||
|
|
||||||
|
return iUnread;
|
||||||
|
};
|
||||||
|
|
||||||
module.exports = new CacheUserStorage();
|
module.exports = new CacheUserStorage();
|
||||||
|
|
||||||
}());
|
}());
|
||||||
|
|
@ -17,12 +17,13 @@
|
||||||
* @constructor
|
* @constructor
|
||||||
* @param {koProperty} oKoList
|
* @param {koProperty} oKoList
|
||||||
* @param {koProperty} oKoSelectedItem
|
* @param {koProperty} oKoSelectedItem
|
||||||
|
* @param {koProperty} oKoFocusedItem
|
||||||
* @param {string} sItemSelector
|
* @param {string} sItemSelector
|
||||||
* @param {string} sItemSelectedSelector
|
* @param {string} sItemSelectedSelector
|
||||||
* @param {string} sItemCheckedSelector
|
* @param {string} sItemCheckedSelector
|
||||||
* @param {string} sItemFocusedSelector
|
* @param {string} sItemFocusedSelector
|
||||||
*/
|
*/
|
||||||
function Selector(oKoList, oKoSelectedItem,
|
function Selector(oKoList, oKoSelectedItem, oKoFocusedItem,
|
||||||
sItemSelector, sItemSelectedSelector, sItemCheckedSelector, sItemFocusedSelector)
|
sItemSelector, sItemSelectedSelector, sItemCheckedSelector, sItemFocusedSelector)
|
||||||
{
|
{
|
||||||
this.list = oKoList;
|
this.list = oKoList;
|
||||||
|
|
@ -37,8 +38,8 @@
|
||||||
return 0 < this.listChecked().length;
|
return 0 < this.listChecked().length;
|
||||||
}, this);
|
}, this);
|
||||||
|
|
||||||
this.focusedItem = ko.observable(null);
|
this.focusedItem = oKoFocusedItem || ko.observable(null);
|
||||||
this.selectedItem = oKoSelectedItem;
|
this.selectedItem = oKoSelectedItem || ko.observable(null);
|
||||||
this.selectedItemUseCallback = true;
|
this.selectedItemUseCallback = true;
|
||||||
|
|
||||||
this.itemSelectedThrottle = _.debounce(_.bind(this.itemSelected, this), 300);
|
this.itemSelectedThrottle = _.debounce(_.bind(this.itemSelected, this), 300);
|
||||||
|
|
|
||||||
|
|
@ -133,18 +133,13 @@
|
||||||
this.sInReplyTo = '';
|
this.sInReplyTo = '';
|
||||||
this.sReferences = '';
|
this.sReferences = '';
|
||||||
|
|
||||||
this.parentUid = ko.observable(0);
|
|
||||||
this.threads = ko.observableArray([]);
|
|
||||||
this.threadsLen = ko.observable(0);
|
|
||||||
this.hasUnseenSubMessage = ko.observable(false);
|
this.hasUnseenSubMessage = ko.observable(false);
|
||||||
this.hasFlaggedSubMessage = ko.observable(false);
|
this.hasFlaggedSubMessage = ko.observable(false);
|
||||||
|
|
||||||
this.lastInCollapsedThread = ko.observable(false);
|
this.threads = ko.observableArray([]);
|
||||||
this.lastInCollapsedThreadLoading = ko.observable(false);
|
|
||||||
|
|
||||||
this.threadsLenResult = ko.computed(function () {
|
this.threadsLen = ko.computed(function () {
|
||||||
var iCount = this.threadsLen();
|
return this.threads().length;
|
||||||
return 0 === this.parentUid() && 0 < iCount ? iCount + 1 : '';
|
|
||||||
}, this);
|
}, this);
|
||||||
|
|
||||||
this.isImportant = ko.computed(function () {
|
this.isImportant = ko.computed(function () {
|
||||||
|
|
@ -152,7 +147,7 @@
|
||||||
}, this);
|
}, this);
|
||||||
|
|
||||||
this.regDisposables([this.attachmentIconClass, this.fullFormatDateValue,
|
this.regDisposables([this.attachmentIconClass, this.fullFormatDateValue,
|
||||||
this.threadsLenResult, this.isImportant]);
|
this.threadsLen, this.isImportant]);
|
||||||
}
|
}
|
||||||
|
|
||||||
_.extend(MessageModel.prototype, AbstractModel.prototype);
|
_.extend(MessageModel.prototype, AbstractModel.prototype);
|
||||||
|
|
@ -349,14 +344,10 @@
|
||||||
this.sInReplyTo = '';
|
this.sInReplyTo = '';
|
||||||
this.sReferences = '';
|
this.sReferences = '';
|
||||||
|
|
||||||
this.parentUid(0);
|
|
||||||
this.threads([]);
|
this.threads([]);
|
||||||
this.threadsLen(0);
|
|
||||||
this.hasUnseenSubMessage(false);
|
this.hasUnseenSubMessage(false);
|
||||||
this.hasFlaggedSubMessage(false);
|
this.hasFlaggedSubMessage(false);
|
||||||
|
|
||||||
this.lastInCollapsedThread(false);
|
|
||||||
this.lastInCollapsedThreadLoading(false);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -435,9 +426,7 @@
|
||||||
this.toEmailsString(MessageModel.emailsToLine(this.to, true));
|
this.toEmailsString(MessageModel.emailsToLine(this.to, true));
|
||||||
this.toClearEmailsString(MessageModel.emailsToLineClear(this.to));
|
this.toClearEmailsString(MessageModel.emailsToLineClear(this.to));
|
||||||
|
|
||||||
this.parentUid(Utils.pInt(oJsonMessage.ParentThread));
|
|
||||||
this.threads(Utils.isArray(oJsonMessage.Threads) ? oJsonMessage.Threads : []);
|
this.threads(Utils.isArray(oJsonMessage.Threads) ? oJsonMessage.Threads : []);
|
||||||
this.threadsLen(Utils.pInt(oJsonMessage.ThreadsLen));
|
|
||||||
|
|
||||||
this.initFlagsByJson(oJsonMessage);
|
this.initFlagsByJson(oJsonMessage);
|
||||||
this.computeSenderEmail();
|
this.computeSenderEmail();
|
||||||
|
|
@ -685,11 +674,7 @@
|
||||||
{
|
{
|
||||||
aResult.push('emptySubject');
|
aResult.push('emptySubject');
|
||||||
}
|
}
|
||||||
if (0 < this.parentUid())
|
if (1 < this.threadsLen())
|
||||||
{
|
|
||||||
aResult.push('hasParentMessage');
|
|
||||||
}
|
|
||||||
if (0 < this.threadsLen() && 0 === this.parentUid())
|
|
||||||
{
|
{
|
||||||
aResult.push('hasChildrenMessage');
|
aResult.push('hasChildrenMessage');
|
||||||
}
|
}
|
||||||
|
|
@ -994,9 +979,7 @@
|
||||||
this.sInReplyTo = '';
|
this.sInReplyTo = '';
|
||||||
this.sReferences = '';
|
this.sReferences = '';
|
||||||
|
|
||||||
this.parentUid(oMessage.parentUid());
|
|
||||||
this.threads(oMessage.threads());
|
this.threads(oMessage.threads());
|
||||||
this.threadsLen(oMessage.threadsLen());
|
|
||||||
|
|
||||||
this.computeSenderEmail();
|
this.computeSenderEmail();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,6 @@
|
||||||
|
|
||||||
AppStore = require('Stores/User/App'),
|
AppStore = require('Stores/User/App'),
|
||||||
SettingsStore = require('Stores/User/Settings'),
|
SettingsStore = require('Stores/User/Settings'),
|
||||||
MessageStore = require('Stores/User/Message'),
|
|
||||||
|
|
||||||
AbstractAjaxRemote = require('Remote/AbstractAjax')
|
AbstractAjaxRemote = require('Remote/AbstractAjax')
|
||||||
;
|
;
|
||||||
|
|
@ -349,7 +348,7 @@
|
||||||
sFolderHash,
|
sFolderHash,
|
||||||
Cache.getFolderInboxName() === sFolderFullNameRaw ? Cache.getFolderUidNext(sFolderFullNameRaw) : '',
|
Cache.getFolderInboxName() === sFolderFullNameRaw ? Cache.getFolderUidNext(sFolderFullNameRaw) : '',
|
||||||
AppStore.threadsAllowed() && SettingsStore.useThreads() ? '1' : '0',
|
AppStore.threadsAllowed() && SettingsStore.useThreads() ? '1' : '0',
|
||||||
AppStore.threadsAllowed() && sFolderFullNameRaw === MessageStore.messageListThreadFolder() ? MessageStore.messageListThreadUids().join(',') : ''
|
''
|
||||||
].join(String.fromCharCode(0))), bSilent ? [] : ['MessageList']);
|
].join(String.fromCharCode(0))), bSilent ? [] : ['MessageList']);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -361,7 +360,6 @@
|
||||||
'Search': sSearch,
|
'Search': sSearch,
|
||||||
'UidNext': Cache.getFolderInboxName() === sFolderFullNameRaw ? Cache.getFolderUidNext(sFolderFullNameRaw) : '',
|
'UidNext': Cache.getFolderInboxName() === sFolderFullNameRaw ? Cache.getFolderUidNext(sFolderFullNameRaw) : '',
|
||||||
'UseThreads': AppStore.threadsAllowed() && SettingsStore.useThreads() ? '1' : '0',
|
'UseThreads': AppStore.threadsAllowed() && SettingsStore.useThreads() ? '1' : '0',
|
||||||
'ExpandedThreadUid': AppStore.threadsAllowed() && sFolderFullNameRaw === MessageStore.messageListThreadFolder() ? MessageStore.messageListThreadUids().join(',') : ''
|
|
||||||
}, '' === sSearch ? Consts.Defaults.DefaultAjaxTimeout : Consts.Defaults.SearchAjaxTimeout, '', bSilent ? [] : ['MessageList']);
|
}, '' === sSearch ? Consts.Defaults.DefaultAjaxTimeout : Consts.Defaults.SearchAjaxTimeout, '', bSilent ? [] : ['MessageList']);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -404,6 +402,35 @@
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {?Function} fCallback
|
||||||
|
* @param {string} sFolderFullNameRaw
|
||||||
|
* @param {number} iUid
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
RemoteUserStorage.prototype.messageThreadsFromCache = function (fCallback, sFolderFullNameRaw, iUid)
|
||||||
|
{
|
||||||
|
sFolderFullNameRaw = Utils.pString(sFolderFullNameRaw);
|
||||||
|
iUid = Utils.pInt(iUid);
|
||||||
|
|
||||||
|
if (Cache.getFolderFromCacheList(sFolderFullNameRaw) && 0 < iUid)
|
||||||
|
{
|
||||||
|
var sFolderHash = Cache.getFolderHash(sFolderFullNameRaw);
|
||||||
|
if (sFolderHash)
|
||||||
|
{
|
||||||
|
this.defaultRequest(fCallback, 'MessageThreadsFromCache', {
|
||||||
|
'Folder': sFolderFullNameRaw,
|
||||||
|
'FolderHash': sFolderHash,
|
||||||
|
'Uid': iUid
|
||||||
|
});
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {?Function} fCallback
|
* @param {?Function} fCallback
|
||||||
* @param {Array} aExternals
|
* @param {Array} aExternals
|
||||||
|
|
|
||||||
|
|
@ -21,9 +21,12 @@
|
||||||
|
|
||||||
Cache = require('Common/Cache'),
|
Cache = require('Common/Cache'),
|
||||||
|
|
||||||
|
AppStore = require('Stores/User/App'),
|
||||||
FolderStore = require('Stores/User/Folder'),
|
FolderStore = require('Stores/User/Folder'),
|
||||||
SettingsStore = require('Stores/User/Settings'),
|
SettingsStore = require('Stores/User/Settings'),
|
||||||
|
|
||||||
|
Remote = require('Remote/User/Ajax'),
|
||||||
|
|
||||||
MessageModel = require('Model/Message')
|
MessageModel = require('Model/Message')
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
@ -41,9 +44,6 @@
|
||||||
this.messageListPage = ko.observable(1);
|
this.messageListPage = ko.observable(1);
|
||||||
this.messageListError = ko.observable('');
|
this.messageListError = ko.observable('');
|
||||||
|
|
||||||
this.messageListThreadFolder = ko.observable('');
|
|
||||||
this.messageListThreadUids = ko.observableArray([]);
|
|
||||||
|
|
||||||
this.messageListEndFolder = ko.observable('');
|
this.messageListEndFolder = ko.observable('');
|
||||||
this.messageListEndSearch = ko.observable('');
|
this.messageListEndSearch = ko.observable('');
|
||||||
this.messageListEndPage = ko.observable(1);
|
this.messageListEndPage = ko.observable(1);
|
||||||
|
|
@ -52,14 +52,29 @@
|
||||||
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.messageListDisableAutoSelect = ko.observable(false).extend({'falseTimeout': 500});
|
||||||
|
|
||||||
// message viewer
|
// message viewer
|
||||||
this.message = ko.observable(null);
|
this.message = ko.observable(null);
|
||||||
this.currentMessage = ko.observable(null);
|
|
||||||
|
this.selectorMessageSelected = ko.observable(null);
|
||||||
|
this.selectorMessageFocused = ko.observable(null);
|
||||||
|
|
||||||
this.message.focused = ko.observable(false);
|
this.message.focused = ko.observable(false);
|
||||||
|
|
||||||
|
this.message.viewTrigger = ko.observable(false);
|
||||||
|
|
||||||
|
this.messageLastThreadUidsData = ko.observable(null);
|
||||||
|
|
||||||
this.messageError = ko.observable('');
|
this.messageError = ko.observable('');
|
||||||
this.messageLoading = ko.observable(false);
|
|
||||||
|
this.messageCurrentLoading = ko.observable(false);
|
||||||
|
this.messageThreadLoading = ko.observable(false);
|
||||||
|
|
||||||
|
this.messageLoading = ko.computed(function () {
|
||||||
|
return !!(this.messageCurrentLoading() || this.messageThreadLoading());
|
||||||
|
}, this);
|
||||||
|
|
||||||
this.messageLoadingThrottle = ko.observable(false).extend({'throttle': 50});
|
this.messageLoadingThrottle = ko.observable(false).extend({'throttle': 50});
|
||||||
|
|
||||||
this.messageFullScreenMode = ko.observable(false);
|
this.messageFullScreenMode = ko.observable(false);
|
||||||
|
|
@ -67,46 +82,11 @@
|
||||||
this.messagesBodiesDom = ko.observable(null);
|
this.messagesBodiesDom = ko.observable(null);
|
||||||
this.messageActiveDom = ko.observable(null);
|
this.messageActiveDom = ko.observable(null);
|
||||||
|
|
||||||
this.messageListChecked = ko.computed(function () {
|
|
||||||
return _.filter(this.messageList(), function (oItem) {
|
|
||||||
return oItem.checked();
|
|
||||||
});
|
|
||||||
}, this).extend({'rateLimit': 0});
|
|
||||||
|
|
||||||
this.hasCheckedMessages = ko.computed(function () {
|
|
||||||
return 0 < this.messageListChecked().length;
|
|
||||||
}, this).extend({'rateLimit': 0});
|
|
||||||
|
|
||||||
this.messageListCheckedOrSelected = ko.computed(function () {
|
|
||||||
|
|
||||||
var
|
|
||||||
aChecked = this.messageListChecked(),
|
|
||||||
oSelectedMessage = this.currentMessage()
|
|
||||||
;
|
|
||||||
|
|
||||||
return _.union(aChecked, oSelectedMessage ? [oSelectedMessage] : []);
|
|
||||||
|
|
||||||
}, this);
|
|
||||||
|
|
||||||
this.messageListCheckedOrSelectedUidsWithSubMails = ko.computed(function () {
|
|
||||||
var aList = [];
|
|
||||||
_.each(this.messageListCheckedOrSelected(), function (oMessage) {
|
|
||||||
if (oMessage)
|
|
||||||
{
|
|
||||||
aList.push(oMessage.uid);
|
|
||||||
if (0 < oMessage.threadsLen() && 0 === oMessage.parentUid() && oMessage.lastInCollapsedThread())
|
|
||||||
{
|
|
||||||
aList = _.union(aList, oMessage.threads());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return aList;
|
|
||||||
}, this);
|
|
||||||
|
|
||||||
|
|
||||||
this.computers();
|
this.computers();
|
||||||
this.subscribers();
|
this.subscribers();
|
||||||
|
|
||||||
|
this.onMessageResponse = _.bind(this.onMessageResponse, this);
|
||||||
|
|
||||||
this.purgeMessageBodyCacheThrottle = _.throttle(this.purgeMessageBodyCache, 1000 * 30);
|
this.purgeMessageBodyCacheThrottle = _.throttle(this.purgeMessageBodyCache, 1000 * 30);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -143,14 +123,46 @@
|
||||||
this.isMessageSelected = ko.computed(function () {
|
this.isMessageSelected = ko.computed(function () {
|
||||||
return null !== this.message();
|
return null !== this.message();
|
||||||
}, this);
|
}, this);
|
||||||
|
|
||||||
|
this.messageListChecked = ko.computed(function () {
|
||||||
|
return _.filter(this.messageList(), function (oItem) {
|
||||||
|
return oItem.checked();
|
||||||
|
});
|
||||||
|
}, this).extend({'rateLimit': 0});
|
||||||
|
|
||||||
|
this.hasCheckedMessages = ko.computed(function () {
|
||||||
|
return 0 < this.messageListChecked().length;
|
||||||
|
}, this).extend({'rateLimit': 0});
|
||||||
|
|
||||||
|
this.messageListCheckedOrSelected = ko.computed(function () {
|
||||||
|
|
||||||
|
var
|
||||||
|
aChecked = this.messageListChecked(),
|
||||||
|
oSelectedMessage = this.selectorMessageSelected()
|
||||||
|
;
|
||||||
|
|
||||||
|
return _.union(aChecked, oSelectedMessage ? [oSelectedMessage] : []);
|
||||||
|
|
||||||
|
}, this);
|
||||||
|
|
||||||
|
this.messageListCheckedOrSelectedUidsWithSubMails = ko.computed(function () {
|
||||||
|
var aList = [];
|
||||||
|
_.each(this.messageListCheckedOrSelected(), function (oMessage) {
|
||||||
|
if (oMessage)
|
||||||
|
{
|
||||||
|
aList.push(oMessage.uid);
|
||||||
|
if (1 < oMessage.threadsLen())
|
||||||
|
{
|
||||||
|
aList = _.union(aList, oMessage.threads());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return aList;
|
||||||
|
}, this);
|
||||||
};
|
};
|
||||||
|
|
||||||
MessageUserStore.prototype.subscribers = function ()
|
MessageUserStore.prototype.subscribers = function ()
|
||||||
{
|
{
|
||||||
this.messageListThreadFolder.subscribe(function () {
|
|
||||||
this.messageListThreadUids([]);
|
|
||||||
}, this);
|
|
||||||
|
|
||||||
this.messageListCompleteLoading.subscribe(function (bValue) {
|
this.messageListCompleteLoading.subscribe(function (bValue) {
|
||||||
this.messageListCompleteLoadingThrottle(bValue);
|
this.messageListCompleteLoadingThrottle(bValue);
|
||||||
}, this);
|
}, this);
|
||||||
|
|
@ -421,11 +433,8 @@
|
||||||
|
|
||||||
if ($oList && 0 < $oList.length)
|
if ($oList && 0 < $oList.length)
|
||||||
{
|
{
|
||||||
_.delay(function () {
|
|
||||||
$oList.each(function () {
|
$oList.each(function () {
|
||||||
var $self = $(this), iH = $self.height();
|
var $self = $(this);
|
||||||
if (0 === iH || 150 < iH)
|
|
||||||
{
|
|
||||||
$self.addClass('rl-bq-switcher hidden-bq');
|
$self.addClass('rl-bq-switcher hidden-bq');
|
||||||
$('<span class="rlBlockquoteSwitcher"><i class="icon-ellipsis" /></span>')
|
$('<span class="rlBlockquoteSwitcher"><i class="icon-ellipsis" /></span>')
|
||||||
.insertBefore($self)
|
.insertBefore($self)
|
||||||
|
|
@ -436,9 +445,7 @@
|
||||||
.after('<br />')
|
.after('<br />')
|
||||||
.before('<br />')
|
.before('<br />')
|
||||||
;
|
;
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}, 100);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -446,6 +453,7 @@
|
||||||
MessageUserStore.prototype.setMessage = function (oData, bCached)
|
MessageUserStore.prototype.setMessage = function (oData, bCached)
|
||||||
{
|
{
|
||||||
var
|
var
|
||||||
|
bNew = false,
|
||||||
bIsHtml = false,
|
bIsHtml = false,
|
||||||
bHasExternals = false,
|
bHasExternals = false,
|
||||||
bHasInternals = false,
|
bHasInternals = false,
|
||||||
|
|
@ -456,11 +464,32 @@
|
||||||
bPgpSigned = false,
|
bPgpSigned = false,
|
||||||
bPgpEncrypted = false,
|
bPgpEncrypted = false,
|
||||||
oMessagesBodiesDom = this.messagesBodiesDom(),
|
oMessagesBodiesDom = this.messagesBodiesDom(),
|
||||||
oMessage = this.message()
|
oSelectedMessage = this.selectorMessageSelected(),
|
||||||
|
oMessage = this.message(),
|
||||||
|
aThreads = []
|
||||||
;
|
;
|
||||||
|
|
||||||
if (oData && oMessage && oData.Result && 'Object/Message' === oData.Result['@Object'] &&
|
if (oData && oMessage && oData.Result && 'Object/Message' === oData.Result['@Object'] &&
|
||||||
oMessage.folderFullNameRaw === oData.Result.Folder && oMessage.uid === oData.Result.Uid)
|
oMessage.folderFullNameRaw === oData.Result.Folder)
|
||||||
|
{
|
||||||
|
aThreads = oMessage.threads();
|
||||||
|
if (oMessage.uid !== oData.Result.Uid && 1 < aThreads.length &&
|
||||||
|
-1 < Utils.inArray(oData.Result.Uid, aThreads))
|
||||||
|
{
|
||||||
|
oMessage = MessageModel.newInstanceFromJson(oData.Result);
|
||||||
|
if (oMessage)
|
||||||
|
{
|
||||||
|
oMessage.threads(aThreads);
|
||||||
|
Cache.initMessageFlagsFromCache(oMessage);
|
||||||
|
|
||||||
|
this.message(this.staticMessage.populateByMessageListItem(oMessage));
|
||||||
|
oMessage = this.message(),
|
||||||
|
|
||||||
|
bNew = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (oMessage && oMessage.uid === oData.Result.Uid)
|
||||||
{
|
{
|
||||||
this.messageError('');
|
this.messageError('');
|
||||||
|
|
||||||
|
|
@ -578,22 +607,140 @@
|
||||||
this.messageActiveDom(oMessage.body);
|
this.messageActiveDom(oMessage.body);
|
||||||
|
|
||||||
this.hideMessageBodies();
|
this.hideMessageBodies();
|
||||||
oMessage.body.show();
|
|
||||||
|
|
||||||
if (oBody)
|
if (oBody)
|
||||||
{
|
{
|
||||||
this.initBlockquoteSwitcher(oBody);
|
this.initBlockquoteSwitcher(oBody);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
oMessage.body.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
Cache.initMessageFlagsFromCache(oMessage);
|
Cache.initMessageFlagsFromCache(oMessage);
|
||||||
if (oMessage.unseen())
|
if (oMessage.unseen() || oMessage.hasUnseenSubMessage())
|
||||||
{
|
{
|
||||||
require('App/User').setMessageSeen(oMessage);
|
require('App/User').messageListAction(oMessage.folderFullNameRaw,
|
||||||
|
oMessage.uid, Enums.MessageSetAction.SetSeen, [oMessage]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bNew)
|
||||||
|
{
|
||||||
|
oMessage = this.message();
|
||||||
|
|
||||||
|
if (oSelectedMessage && oMessage && (
|
||||||
|
oMessage.folderFullNameRaw !== oSelectedMessage.folderFullNameRaw ||
|
||||||
|
oMessage.uid !== oSelectedMessage.uid
|
||||||
|
))
|
||||||
|
{
|
||||||
|
this.selectorMessageSelected(null);
|
||||||
|
if (1 === this.messageList().length)
|
||||||
|
{
|
||||||
|
this.selectorMessageFocused(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!oSelectedMessage && oMessage)
|
||||||
|
{
|
||||||
|
oSelectedMessage = _.find(this.messageList(), function (oSubMessage) {
|
||||||
|
return oSubMessage &&
|
||||||
|
oSubMessage.folderFullNameRaw === oMessage.folderFullNameRaw &&
|
||||||
|
oSubMessage.uid === oMessage.uid;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (oSelectedMessage)
|
||||||
|
{
|
||||||
|
this.selectorMessageSelected(oSelectedMessage);
|
||||||
|
this.selectorMessageFocused(oSelectedMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Utils.windowResize();
|
Utils.windowResize();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
MessageUserStore.prototype.selectMessage = function (oMessage)
|
||||||
|
{
|
||||||
|
if (oMessage)
|
||||||
|
{
|
||||||
|
this.message(this.staticMessage.populateByMessageListItem(oMessage));
|
||||||
|
|
||||||
|
this.populateMessageBody(this.message());
|
||||||
|
|
||||||
|
if (Enums.Layout.NoPreview === SettingsStore.layout())
|
||||||
|
{
|
||||||
|
kn.setHash(Links.messagePreview(), true);
|
||||||
|
this.message.focused(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.message(null);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
MessageUserStore.prototype.selectThreadMessage = function (sFolder, sUid)
|
||||||
|
{
|
||||||
|
if (Remote.message(this.onMessageResponse, sFolder, sUid))
|
||||||
|
{
|
||||||
|
this.messageThreadLoading(true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Utils.log('Error: Unknown message request: ' + sFolder + ' ~ ' + sUid + ' [e-102]');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Enums.Layout.NoPreview === SettingsStore.layout())
|
||||||
|
{
|
||||||
|
kn.setHash(Links.messagePreview(), true);
|
||||||
|
this.message.focused(true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
MessageUserStore.prototype.populateMessageBody = function (oMessage)
|
||||||
|
{
|
||||||
|
if (oMessage)
|
||||||
|
{
|
||||||
|
if (Remote.message(this.onMessageResponse, oMessage.folderFullNameRaw, oMessage.uid))
|
||||||
|
{
|
||||||
|
this.messageCurrentLoading(true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Utils.log('Error: Unknown message request: ' + oMessage.folderFullNameRaw + ' ~ ' + oMessage.uid + ' [e-101]');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} sResult
|
||||||
|
* @param {AjaxJsonDefaultResponse} oData
|
||||||
|
* @param {boolean} bCached
|
||||||
|
*/
|
||||||
|
MessageUserStore.prototype.onMessageResponse = function (sResult, oData, bCached)
|
||||||
|
{
|
||||||
|
this.hideMessageBodies();
|
||||||
|
|
||||||
|
this.messageCurrentLoading(false);
|
||||||
|
this.messageThreadLoading(false);
|
||||||
|
|
||||||
|
if (Enums.StorageResultType.Success === sResult && oData && oData.Result)
|
||||||
|
{
|
||||||
|
this.setMessage(oData, bCached);
|
||||||
|
}
|
||||||
|
else if (Enums.StorageResultType.Unload === sResult)
|
||||||
|
{
|
||||||
|
this.message(null);
|
||||||
|
this.messageError('');
|
||||||
|
}
|
||||||
|
else if (Enums.StorageResultType.Abort !== sResult)
|
||||||
|
{
|
||||||
|
this.message(null);
|
||||||
|
this.messageError((oData && oData.ErrorCode ?
|
||||||
|
Translator.getNotification(oData.ErrorCode) :
|
||||||
|
Translator.getNotification(Enums.Notification.UnknownError)));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -613,7 +760,7 @@
|
||||||
oData.Result['@Collection'] && Utils.isArray(oData.Result['@Collection']))
|
oData.Result['@Collection'] && Utils.isArray(oData.Result['@Collection']))
|
||||||
{
|
{
|
||||||
var
|
var
|
||||||
mLastCollapsedThreadUids = null,
|
self = this,
|
||||||
iIndex = 0,
|
iIndex = 0,
|
||||||
iLen = 0,
|
iLen = 0,
|
||||||
iCount = 0,
|
iCount = 0,
|
||||||
|
|
@ -630,11 +777,6 @@
|
||||||
iCount = Utils.pInt(oData.Result.MessageResultCount);
|
iCount = Utils.pInt(oData.Result.MessageResultCount);
|
||||||
iOffset = Utils.pInt(oData.Result.Offset);
|
iOffset = Utils.pInt(oData.Result.Offset);
|
||||||
|
|
||||||
if (Utils.isNonEmptyArray(oData.Result.LastCollapsedThreadUids))
|
|
||||||
{
|
|
||||||
mLastCollapsedThreadUids = oData.Result.LastCollapsedThreadUids;
|
|
||||||
}
|
|
||||||
|
|
||||||
oFolder = Cache.getFolderFromCacheList(
|
oFolder = Cache.getFolderFromCacheList(
|
||||||
Utils.isNormal(oData.Result.Folder) ? oData.Result.Folder : '');
|
Utils.isNormal(oData.Result.Folder) ? oData.Result.Folder : '');
|
||||||
|
|
||||||
|
|
@ -692,9 +834,6 @@
|
||||||
Cache.storeMessageFlagsToCache(oMessage);
|
Cache.storeMessageFlagsToCache(oMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
oMessage.lastInCollapsedThreadLoading(false);
|
|
||||||
oMessage.lastInCollapsedThread(mLastCollapsedThreadUids && -1 < Utils.inArray(Utils.pInt(oMessage.uid), mLastCollapsedThreadUids) ? true : false);
|
|
||||||
|
|
||||||
aList.push(oMessage);
|
aList.push(oMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -708,11 +847,33 @@
|
||||||
this.messageListEndSearch(Utils.isNormal(oData.Result.Search) ? oData.Result.Search : '');
|
this.messageListEndSearch(Utils.isNormal(oData.Result.Search) ? oData.Result.Search : '');
|
||||||
this.messageListEndPage(this.messageListPage());
|
this.messageListEndPage(this.messageListPage());
|
||||||
|
|
||||||
|
this.messageListDisableAutoSelect(true);
|
||||||
|
|
||||||
this.messageList(aList);
|
this.messageList(aList);
|
||||||
this.messageListIsNotCompleted(false);
|
this.messageListIsNotCompleted(false);
|
||||||
|
|
||||||
Cache.clearNewMessageCache();
|
Cache.clearNewMessageCache();
|
||||||
|
|
||||||
|
if (AppStore.threadsAllowed() && SettingsStore.useThreads())
|
||||||
|
{
|
||||||
|
oMessage = this.message();
|
||||||
|
if (oMessage)
|
||||||
|
{
|
||||||
|
Remote.messageThreadsFromCache(function (sResult, oData) {
|
||||||
|
|
||||||
|
if (Enums.StorageResultType.Success === sResult && oData && oData.Result && oData.Result.ThreadUids)
|
||||||
|
{
|
||||||
|
self.messageLastThreadUidsData({
|
||||||
|
'Folder': oData.Result.Folder,
|
||||||
|
'Uid': oData.Result.Uid,
|
||||||
|
'Uids': oData.Result.ThreadUids
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}, oMessage.folderFullNameRaw, oMessage.uid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (oFolder && (bCached || bUnreadCountChange || SettingsStore.useThreads()))
|
if (oFolder && (bCached || bUnreadCountChange || SettingsStore.useThreads()))
|
||||||
{
|
{
|
||||||
require('App/User').folderInformation(oFolder.fullNameRaw, aList);
|
require('App/User').folderInformation(oFolder.fullNameRaw, aList);
|
||||||
|
|
|
||||||
|
|
@ -110,7 +110,6 @@ html.rl-no-preview-pane {
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
margin-left: 3px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.senderParent {
|
.senderParent {
|
||||||
|
|
@ -121,8 +120,25 @@ 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: 15px;
|
margin-left: 22px;
|
||||||
a {
|
a {
|
||||||
.g-ui-link;
|
.g-ui-link;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -208,7 +208,7 @@
|
||||||
});
|
});
|
||||||
}, this);
|
}, this);
|
||||||
|
|
||||||
this.selector = new Selector(this.contacts, this.currentContact,
|
this.selector = new Selector(this.contacts, this.currentContact, null,
|
||||||
'.e-contact-item .actionHandle', '.e-contact-item.selected', '.e-contact-item .checkboxItem',
|
'.e-contact-item .actionHandle', '.e-contact-item.selected', '.e-contact-item .checkboxItem',
|
||||||
'.e-contact-item.focused');
|
'.e-contact-item.focused');
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -52,8 +52,10 @@
|
||||||
|
|
||||||
this.message = MessageStore.message;
|
this.message = MessageStore.message;
|
||||||
this.messageList = MessageStore.messageList;
|
this.messageList = MessageStore.messageList;
|
||||||
|
this.messageListDisableAutoSelect = MessageStore.messageListDisableAutoSelect;
|
||||||
this.folderList = FolderStore.folderList;
|
this.folderList = FolderStore.folderList;
|
||||||
this.currentMessage = MessageStore.currentMessage;
|
this.selectorMessageSelected = MessageStore.selectorMessageSelected;
|
||||||
|
this.selectorMessageFocused = MessageStore.selectorMessageFocused;
|
||||||
this.isMessageSelected = MessageStore.isMessageSelected;
|
this.isMessageSelected = MessageStore.isMessageSelected;
|
||||||
this.messageListSearch = MessageStore.messageListSearch;
|
this.messageListSearch = MessageStore.messageListSearch;
|
||||||
this.messageListError = MessageStore.messageListError;
|
this.messageListError = MessageStore.messageListError;
|
||||||
|
|
@ -224,27 +226,12 @@
|
||||||
|
|
||||||
this.quotaTooltip = _.bind(this.quotaTooltip, this);
|
this.quotaTooltip = _.bind(this.quotaTooltip, this);
|
||||||
|
|
||||||
this.selector = new Selector(this.messageList, this.currentMessage,
|
this.selector = new Selector(this.messageList, this.selectorMessageSelected, this.selectorMessageFocused,
|
||||||
'.messageListItem .actionHandle', '.messageListItem.selected', '.messageListItem .checkboxMessage',
|
'.messageListItem .actionHandle', '.messageListItem.selected', '.messageListItem .checkboxMessage',
|
||||||
'.messageListItem.focused');
|
'.messageListItem.focused');
|
||||||
|
|
||||||
this.selector.on('onItemSelect', _.bind(function (oMessage) {
|
this.selector.on('onItemSelect', _.bind(function (oMessage) {
|
||||||
if (oMessage)
|
MessageStore.selectMessage(oMessage);
|
||||||
{
|
|
||||||
MessageStore.message(MessageStore.staticMessage.populateByMessageListItem(oMessage));
|
|
||||||
|
|
||||||
this.populateMessageBody(MessageStore.message());
|
|
||||||
|
|
||||||
if (Enums.Layout.NoPreview === SettingsStore.layout())
|
|
||||||
{
|
|
||||||
kn.setHash(Links.messagePreview(), true);
|
|
||||||
MessageStore.message.focused(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
MessageStore.message(null);
|
|
||||||
}
|
|
||||||
}, this));
|
}, this));
|
||||||
|
|
||||||
this.selector.on('onItemGetUid', function (oMessage) {
|
this.selector.on('onItemGetUid', function (oMessage) {
|
||||||
|
|
@ -281,6 +268,11 @@
|
||||||
|
|
||||||
MessageListMailBoxUserView.prototype.useAutoSelect = function ()
|
MessageListMailBoxUserView.prototype.useAutoSelect = function ()
|
||||||
{
|
{
|
||||||
|
if (this.messageListDisableAutoSelect())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (/is:unseen/.test(this.mainMessageListSearch()))
|
if (/is:unseen/.test(this.mainMessageListSearch()))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -353,129 +345,15 @@
|
||||||
return oEl;
|
return oEl;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {string} sResult
|
|
||||||
* @param {AjaxJsonDefaultResponse} oData
|
|
||||||
* @param {boolean} bCached
|
|
||||||
*/
|
|
||||||
MessageListMailBoxUserView.prototype.onMessageResponse = function (sResult, oData, bCached)
|
|
||||||
{
|
|
||||||
MessageStore.hideMessageBodies();
|
|
||||||
MessageStore.messageLoading(false);
|
|
||||||
|
|
||||||
if (Enums.StorageResultType.Success === sResult && oData && oData.Result)
|
|
||||||
{
|
|
||||||
MessageStore.setMessage(oData, bCached);
|
|
||||||
}
|
|
||||||
else if (Enums.StorageResultType.Unload === sResult)
|
|
||||||
{
|
|
||||||
MessageStore.message(null);
|
|
||||||
MessageStore.messageError('');
|
|
||||||
}
|
|
||||||
else if (Enums.StorageResultType.Abort !== sResult)
|
|
||||||
{
|
|
||||||
MessageStore.message(null);
|
|
||||||
MessageStore.messageError((oData && oData.ErrorCode ?
|
|
||||||
Translator.getNotification(oData.ErrorCode) :
|
|
||||||
Translator.getNotification(Enums.Notification.UnknownError)));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
MessageListMailBoxUserView.prototype.populateMessageBody = function (oMessage)
|
|
||||||
{
|
|
||||||
if (oMessage)
|
|
||||||
{
|
|
||||||
if (Remote.message(this.onMessageResponse, oMessage.folderFullNameRaw, oMessage.uid))
|
|
||||||
{
|
|
||||||
MessageStore.messageLoading(true);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Utils.log('Error: Unknown message request: ' + oMessage.folderFullNameRaw + ' ~ ' + oMessage.uid + ' [e-101]');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string} sFolderFullNameRaw
|
* @param {string} sFolderFullNameRaw
|
||||||
|
* @param {string|bool} sUid
|
||||||
* @param {number} iSetAction
|
* @param {number} iSetAction
|
||||||
* @param {Array=} aMessages = null
|
* @param {Array=} aMessages = null
|
||||||
*/
|
*/
|
||||||
MessageListMailBoxUserView.prototype.setAction = function (sFolderFullNameRaw, iSetAction, aMessages)
|
MessageListMailBoxUserView.prototype.setAction = function (sFolderFullNameRaw, mUid, iSetAction, aMessages)
|
||||||
{
|
{
|
||||||
var
|
require('App/User').messageListAction(sFolderFullNameRaw, mUid, iSetAction, aMessages);
|
||||||
aUids = [],
|
|
||||||
oFolder = null,
|
|
||||||
iAlreadyUnread = 0
|
|
||||||
;
|
|
||||||
|
|
||||||
if (Utils.isUnd(aMessages))
|
|
||||||
{
|
|
||||||
aMessages = MessageStore.messageListChecked();
|
|
||||||
}
|
|
||||||
|
|
||||||
aUids = _.map(aMessages, function (oMessage) {
|
|
||||||
return oMessage.uid;
|
|
||||||
});
|
|
||||||
|
|
||||||
if ('' !== sFolderFullNameRaw && 0 < aUids.length)
|
|
||||||
{
|
|
||||||
switch (iSetAction) {
|
|
||||||
case Enums.MessageSetAction.SetSeen:
|
|
||||||
_.each(aMessages, function (oMessage) {
|
|
||||||
if (oMessage.unseen())
|
|
||||||
{
|
|
||||||
iAlreadyUnread++;
|
|
||||||
}
|
|
||||||
|
|
||||||
oMessage.unseen(false);
|
|
||||||
Cache.storeMessageFlagsToCache(oMessage);
|
|
||||||
});
|
|
||||||
|
|
||||||
oFolder = Cache.getFolderFromCacheList(sFolderFullNameRaw);
|
|
||||||
if (oFolder)
|
|
||||||
{
|
|
||||||
oFolder.messageCountUnread(oFolder.messageCountUnread() - iAlreadyUnread);
|
|
||||||
}
|
|
||||||
|
|
||||||
Remote.messageSetSeen(Utils.emptyFunction, sFolderFullNameRaw, aUids, true);
|
|
||||||
break;
|
|
||||||
case Enums.MessageSetAction.UnsetSeen:
|
|
||||||
_.each(aMessages, function (oMessage) {
|
|
||||||
if (oMessage.unseen())
|
|
||||||
{
|
|
||||||
iAlreadyUnread++;
|
|
||||||
}
|
|
||||||
|
|
||||||
oMessage.unseen(true);
|
|
||||||
Cache.storeMessageFlagsToCache(oMessage);
|
|
||||||
});
|
|
||||||
|
|
||||||
oFolder = Cache.getFolderFromCacheList(sFolderFullNameRaw);
|
|
||||||
if (oFolder)
|
|
||||||
{
|
|
||||||
oFolder.messageCountUnread(oFolder.messageCountUnread() - iAlreadyUnread + aUids.length);
|
|
||||||
}
|
|
||||||
Remote.messageSetSeen(Utils.emptyFunction, sFolderFullNameRaw, aUids, false);
|
|
||||||
break;
|
|
||||||
case Enums.MessageSetAction.SetFlag:
|
|
||||||
_.each(aMessages, function (oMessage) {
|
|
||||||
oMessage.flagged(true);
|
|
||||||
Cache.storeMessageFlagsToCache(oMessage);
|
|
||||||
});
|
|
||||||
Remote.messageSetFlagged(Utils.emptyFunction, sFolderFullNameRaw, aUids, true);
|
|
||||||
break;
|
|
||||||
case Enums.MessageSetAction.UnsetFlag:
|
|
||||||
_.each(aMessages, function (oMessage) {
|
|
||||||
oMessage.flagged(false);
|
|
||||||
Cache.storeMessageFlagsToCache(oMessage);
|
|
||||||
});
|
|
||||||
Remote.messageSetFlagged(Utils.emptyFunction, sFolderFullNameRaw, aUids, false);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
require('App/User').reloadFlagsCurrentMessageListAndMessageFromCache();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -532,8 +410,8 @@
|
||||||
|
|
||||||
MessageListMailBoxUserView.prototype.listSetSeen = function ()
|
MessageListMailBoxUserView.prototype.listSetSeen = function ()
|
||||||
{
|
{
|
||||||
this.setAction(FolderStore.currentFolderFullNameRaw(), Enums.MessageSetAction.SetSeen,
|
this.setAction(FolderStore.currentFolderFullNameRaw(), true,
|
||||||
MessageStore.messageListCheckedOrSelected());
|
Enums.MessageSetAction.SetSeen, MessageStore.messageListCheckedOrSelected());
|
||||||
};
|
};
|
||||||
|
|
||||||
MessageListMailBoxUserView.prototype.listSetAllSeen = function ()
|
MessageListMailBoxUserView.prototype.listSetAllSeen = function ()
|
||||||
|
|
@ -543,20 +421,20 @@
|
||||||
|
|
||||||
MessageListMailBoxUserView.prototype.listUnsetSeen = function ()
|
MessageListMailBoxUserView.prototype.listUnsetSeen = function ()
|
||||||
{
|
{
|
||||||
this.setAction(FolderStore.currentFolderFullNameRaw(), Enums.MessageSetAction.UnsetSeen,
|
this.setAction(FolderStore.currentFolderFullNameRaw(), true,
|
||||||
MessageStore.messageListCheckedOrSelected());
|
Enums.MessageSetAction.UnsetSeen, MessageStore.messageListCheckedOrSelected());
|
||||||
};
|
};
|
||||||
|
|
||||||
MessageListMailBoxUserView.prototype.listSetFlags = function ()
|
MessageListMailBoxUserView.prototype.listSetFlags = function ()
|
||||||
{
|
{
|
||||||
this.setAction(FolderStore.currentFolderFullNameRaw(), Enums.MessageSetAction.SetFlag,
|
this.setAction(FolderStore.currentFolderFullNameRaw(), true,
|
||||||
MessageStore.messageListCheckedOrSelected());
|
Enums.MessageSetAction.SetFlag, MessageStore.messageListCheckedOrSelected());
|
||||||
};
|
};
|
||||||
|
|
||||||
MessageListMailBoxUserView.prototype.listUnsetFlags = function ()
|
MessageListMailBoxUserView.prototype.listUnsetFlags = function ()
|
||||||
{
|
{
|
||||||
this.setAction(FolderStore.currentFolderFullNameRaw(), Enums.MessageSetAction.UnsetFlag,
|
this.setAction(FolderStore.currentFolderFullNameRaw(), true,
|
||||||
MessageStore.messageListCheckedOrSelected());
|
Enums.MessageSetAction.UnsetFlag, MessageStore.messageListCheckedOrSelected());
|
||||||
};
|
};
|
||||||
|
|
||||||
MessageListMailBoxUserView.prototype.flagMessages = function (oCurrentMessage)
|
MessageListMailBoxUserView.prototype.flagMessages = function (oCurrentMessage)
|
||||||
|
|
@ -577,12 +455,12 @@
|
||||||
|
|
||||||
if (0 < aCheckedUids.length && -1 < Utils.inArray(oCurrentMessage.uid, aCheckedUids))
|
if (0 < aCheckedUids.length && -1 < Utils.inArray(oCurrentMessage.uid, aCheckedUids))
|
||||||
{
|
{
|
||||||
this.setAction(oCurrentMessage.folderFullNameRaw, oCurrentMessage.flagged() ?
|
this.setAction(oCurrentMessage.folderFullNameRaw, true, oCurrentMessage.flagged() ?
|
||||||
Enums.MessageSetAction.UnsetFlag : Enums.MessageSetAction.SetFlag, aChecked);
|
Enums.MessageSetAction.UnsetFlag : Enums.MessageSetAction.SetFlag, aChecked);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
this.setAction(oCurrentMessage.folderFullNameRaw, oCurrentMessage.flagged() ?
|
this.setAction(oCurrentMessage.folderFullNameRaw, true, oCurrentMessage.flagged() ?
|
||||||
Enums.MessageSetAction.UnsetFlag : Enums.MessageSetAction.SetFlag, [oCurrentMessage]);
|
Enums.MessageSetAction.UnsetFlag : Enums.MessageSetAction.SetFlag, [oCurrentMessage]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -603,12 +481,12 @@
|
||||||
|
|
||||||
if (Utils.isUnd(bFlag))
|
if (Utils.isUnd(bFlag))
|
||||||
{
|
{
|
||||||
this.setAction(aChecked[0].folderFullNameRaw,
|
this.setAction(aChecked[0].folderFullNameRaw, true,
|
||||||
aChecked.length === aFlagged.length ? Enums.MessageSetAction.UnsetFlag : Enums.MessageSetAction.SetFlag, aChecked);
|
aChecked.length === aFlagged.length ? Enums.MessageSetAction.UnsetFlag : Enums.MessageSetAction.SetFlag, aChecked);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
this.setAction(aChecked[0].folderFullNameRaw,
|
this.setAction(aChecked[0].folderFullNameRaw, true,
|
||||||
!bFlag ? Enums.MessageSetAction.UnsetFlag : Enums.MessageSetAction.SetFlag, aChecked);
|
!bFlag ? Enums.MessageSetAction.UnsetFlag : Enums.MessageSetAction.SetFlag, aChecked);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -629,12 +507,12 @@
|
||||||
|
|
||||||
if (Utils.isUnd(bSeen))
|
if (Utils.isUnd(bSeen))
|
||||||
{
|
{
|
||||||
this.setAction(aChecked[0].folderFullNameRaw,
|
this.setAction(aChecked[0].folderFullNameRaw, true,
|
||||||
0 < aUnseen.length ? Enums.MessageSetAction.SetSeen : Enums.MessageSetAction.UnsetSeen, aChecked);
|
0 < aUnseen.length ? Enums.MessageSetAction.SetSeen : Enums.MessageSetAction.UnsetSeen, aChecked);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
this.setAction(aChecked[0].folderFullNameRaw,
|
this.setAction(aChecked[0].folderFullNameRaw, true,
|
||||||
bSeen ? Enums.MessageSetAction.SetSeen : Enums.MessageSetAction.UnsetSeen, aChecked);
|
bSeen ? Enums.MessageSetAction.SetSeen : Enums.MessageSetAction.UnsetSeen, aChecked);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -647,38 +525,6 @@
|
||||||
this.oContentVisible = $('.b-content', oDom);
|
this.oContentVisible = $('.b-content', oDom);
|
||||||
this.oContentScrollable = $('.content', this.oContentVisible);
|
this.oContentScrollable = $('.content', this.oContentVisible);
|
||||||
|
|
||||||
this.oContentVisible.on('click', '.fullThreadHandle', function () {
|
|
||||||
var
|
|
||||||
aList = [],
|
|
||||||
oMessage = ko.dataFor(this)
|
|
||||||
;
|
|
||||||
|
|
||||||
if (oMessage && !oMessage.lastInCollapsedThreadLoading())
|
|
||||||
{
|
|
||||||
MessageStore.messageListThreadFolder(oMessage.folderFullNameRaw);
|
|
||||||
|
|
||||||
aList = MessageStore.messageListThreadUids();
|
|
||||||
|
|
||||||
if (oMessage.lastInCollapsedThread())
|
|
||||||
{
|
|
||||||
aList.push(0 < oMessage.parentUid() ? oMessage.parentUid() : oMessage.uid);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
aList = _.without(aList, 0 < oMessage.parentUid() ? oMessage.parentUid() : oMessage.uid);
|
|
||||||
}
|
|
||||||
|
|
||||||
MessageStore.messageListThreadUids(_.uniq(aList));
|
|
||||||
|
|
||||||
oMessage.lastInCollapsedThreadLoading(true);
|
|
||||||
oMessage.lastInCollapsedThread(!oMessage.lastInCollapsedThread());
|
|
||||||
|
|
||||||
require('App/User').reloadMessageList();
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
this.selector.init(this.oContentVisible, this.oContentScrollable, Enums.KeyState.MessageList);
|
this.selector.init(this.oContentVisible, this.oContentScrollable, Enums.KeyState.MessageList);
|
||||||
|
|
||||||
oDom
|
oDom
|
||||||
|
|
|
||||||
|
|
@ -58,11 +58,9 @@
|
||||||
this.pswp = null;
|
this.pswp = null;
|
||||||
|
|
||||||
this.message = MessageStore.message;
|
this.message = MessageStore.message;
|
||||||
this.currentMessage = MessageStore.currentMessage;
|
|
||||||
this.messageListChecked = MessageStore.messageListChecked;
|
this.messageListChecked = MessageStore.messageListChecked;
|
||||||
this.hasCheckedMessages = MessageStore.hasCheckedMessages;
|
this.hasCheckedMessages = MessageStore.hasCheckedMessages;
|
||||||
this.messageListCheckedOrSelectedUidsWithSubMails = MessageStore.messageListCheckedOrSelectedUidsWithSubMails;
|
this.messageListCheckedOrSelectedUidsWithSubMails = MessageStore.messageListCheckedOrSelectedUidsWithSubMails;
|
||||||
this.messageLoading = MessageStore.messageLoading;
|
|
||||||
this.messageLoadingThrottle = MessageStore.messageLoadingThrottle;
|
this.messageLoadingThrottle = MessageStore.messageLoadingThrottle;
|
||||||
this.messagesBodiesDom = MessageStore.messagesBodiesDom;
|
this.messagesBodiesDom = MessageStore.messagesBodiesDom;
|
||||||
this.useThreads = SettingsStore.useThreads;
|
this.useThreads = SettingsStore.useThreads;
|
||||||
|
|
@ -103,7 +101,7 @@
|
||||||
this.message.subscribe(function (oMessage) {
|
this.message.subscribe(function (oMessage) {
|
||||||
if (!oMessage)
|
if (!oMessage)
|
||||||
{
|
{
|
||||||
this.currentMessage(null);
|
MessageStore.selectorMessageSelected(null);
|
||||||
}
|
}
|
||||||
}, this);
|
}, this);
|
||||||
|
|
||||||
|
|
@ -130,47 +128,52 @@
|
||||||
}, this.messageVisibility);
|
}, this.messageVisibility);
|
||||||
|
|
||||||
this.deleteCommand = Utils.createCommand(this, function () {
|
this.deleteCommand = Utils.createCommand(this, function () {
|
||||||
if (this.message())
|
var oMessage = this.message();
|
||||||
|
if (oMessage)
|
||||||
{
|
{
|
||||||
|
this.message(null);
|
||||||
require('App/User').deleteMessagesFromFolder(Enums.FolderType.Trash,
|
require('App/User').deleteMessagesFromFolder(Enums.FolderType.Trash,
|
||||||
this.message().folderFullNameRaw,
|
oMessage.folderFullNameRaw, [oMessage.uid], true);
|
||||||
[this.message().uid], true);
|
|
||||||
}
|
}
|
||||||
}, this.messageVisibility);
|
}, this.messageVisibility);
|
||||||
|
|
||||||
this.deleteWithoutMoveCommand = Utils.createCommand(this, function () {
|
this.deleteWithoutMoveCommand = Utils.createCommand(this, function () {
|
||||||
if (this.message())
|
var oMessage = this.message();
|
||||||
|
if (oMessage)
|
||||||
{
|
{
|
||||||
|
this.message(null);
|
||||||
require('App/User').deleteMessagesFromFolder(Enums.FolderType.Trash,
|
require('App/User').deleteMessagesFromFolder(Enums.FolderType.Trash,
|
||||||
FolderStore.currentFolderFullNameRaw(),
|
oMessage.folderFullNameRaw, [oMessage.uid], false);
|
||||||
[this.message().uid], false);
|
|
||||||
}
|
}
|
||||||
}, this.messageVisibility);
|
}, this.messageVisibility);
|
||||||
|
|
||||||
this.archiveCommand = Utils.createCommand(this, function () {
|
this.archiveCommand = Utils.createCommand(this, function () {
|
||||||
if (this.message())
|
var oMessage = this.message();
|
||||||
|
if (oMessage)
|
||||||
{
|
{
|
||||||
|
this.message(null);
|
||||||
require('App/User').deleteMessagesFromFolder(Enums.FolderType.Archive,
|
require('App/User').deleteMessagesFromFolder(Enums.FolderType.Archive,
|
||||||
this.message().folderFullNameRaw,
|
oMessage.folderFullNameRaw, [oMessage.uid], true);
|
||||||
[this.message().uid], true);
|
|
||||||
}
|
}
|
||||||
}, this.messageVisibility);
|
}, this.messageVisibility);
|
||||||
|
|
||||||
this.spamCommand = Utils.createCommand(this, function () {
|
this.spamCommand = Utils.createCommand(this, function () {
|
||||||
if (this.message())
|
var oMessage = this.message();
|
||||||
|
if (oMessage)
|
||||||
{
|
{
|
||||||
|
this.message(null);
|
||||||
require('App/User').deleteMessagesFromFolder(Enums.FolderType.Spam,
|
require('App/User').deleteMessagesFromFolder(Enums.FolderType.Spam,
|
||||||
this.message().folderFullNameRaw,
|
oMessage.folderFullNameRaw, [oMessage.uid], true);
|
||||||
[this.message().uid], true);
|
|
||||||
}
|
}
|
||||||
}, this.messageVisibility);
|
}, this.messageVisibility);
|
||||||
|
|
||||||
this.notSpamCommand = Utils.createCommand(this, function () {
|
this.notSpamCommand = Utils.createCommand(this, function () {
|
||||||
if (this.message())
|
var oMessage = this.message();
|
||||||
|
if (oMessage)
|
||||||
{
|
{
|
||||||
|
this.message(null);
|
||||||
require('App/User').deleteMessagesFromFolder(Enums.FolderType.NotSpam,
|
require('App/User').deleteMessagesFromFolder(Enums.FolderType.NotSpam,
|
||||||
this.message().folderFullNameRaw,
|
oMessage.folderFullNameRaw, [oMessage.uid], true);
|
||||||
[this.message().uid], true);
|
|
||||||
}
|
}
|
||||||
}, this.messageVisibility);
|
}, this.messageVisibility);
|
||||||
|
|
||||||
|
|
@ -178,6 +181,8 @@
|
||||||
|
|
||||||
this.viewBodyTopValue = ko.observable(0);
|
this.viewBodyTopValue = ko.observable(0);
|
||||||
|
|
||||||
|
this.viewFolder = '';
|
||||||
|
this.viewUid = '';
|
||||||
this.viewHash = '';
|
this.viewHash = '';
|
||||||
this.viewSubject = ko.observable('');
|
this.viewSubject = ko.observable('');
|
||||||
this.viewFromShort = ko.observable('');
|
this.viewFromShort = ko.observable('');
|
||||||
|
|
@ -197,7 +202,94 @@
|
||||||
this.viewUserPic = ko.observable(Consts.DataImages.UserDotPic);
|
this.viewUserPic = ko.observable(Consts.DataImages.UserDotPic);
|
||||||
this.viewUserPicVisible = ko.observable(false);
|
this.viewUserPicVisible = ko.observable(false);
|
||||||
this.viewIsImportant = ko.observable(false);
|
this.viewIsImportant = ko.observable(false);
|
||||||
|
this.viewIsFlagged = ko.observable(false);
|
||||||
|
|
||||||
|
// THREADS
|
||||||
|
this.viewThreads = ko.observableArray([]);
|
||||||
|
this.viewThreads.trigger = ko.observable(false);
|
||||||
|
|
||||||
|
MessageStore.messageLastThreadUidsData.subscribe(function (oData) {
|
||||||
|
if (oData && oData['Uids'])
|
||||||
|
{
|
||||||
|
oData['Uid'] = Utils.pString(oData['Uid']);
|
||||||
|
if (this.viewFolder === oData['Folder'] && this.viewUid === oData['Uid'])
|
||||||
|
{
|
||||||
|
this.viewThreads(oData['Uids']);
|
||||||
|
this.viewThreads.trigger(!this.viewThreads.trigger());
|
||||||
|
}
|
||||||
|
|
||||||
|
var oMessage = MessageStore.message();
|
||||||
|
if (oMessage && oMessage.folderFullNameRaw === oData['Folder'] && oMessage.uid === oData['Uid'])
|
||||||
|
{
|
||||||
|
oMessage.threads(oData['Uids']);
|
||||||
|
}
|
||||||
|
|
||||||
|
oMessage = _.find(MessageStore.messageList(), function (oMessage) {
|
||||||
|
return oMessage && oMessage.folderFullNameRaw === oData['Folder'] && oMessage.uid === oData['Uid'];
|
||||||
|
});
|
||||||
|
|
||||||
|
if (oMessage && oMessage.folderFullNameRaw === oData['Folder'] && oMessage.uid === oData['Uid'])
|
||||||
|
{
|
||||||
|
oMessage.threads(oData['Uids']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, this);
|
||||||
|
|
||||||
|
this.viewThreads.status = ko.computed(function () {
|
||||||
|
|
||||||
|
this.viewThreads.trigger();
|
||||||
|
|
||||||
|
var
|
||||||
|
iIndex = 0,
|
||||||
|
aResult = [false, '', '', '', ''],
|
||||||
|
aThreads = this.viewThreads.peek(),
|
||||||
|
iLen = aThreads.length
|
||||||
|
;
|
||||||
|
|
||||||
|
if (1 < iLen)
|
||||||
|
{
|
||||||
|
iIndex = Utils.inArray(this.viewUid, aThreads);
|
||||||
|
if (-1 < iIndex)
|
||||||
|
{
|
||||||
|
aResult[0] = true;
|
||||||
|
aResult[1] = (iIndex + 1) + ' / ' + iLen;
|
||||||
|
aResult[2] = aThreads[iIndex];
|
||||||
|
aResult[3] = 0 < iIndex && aThreads[iIndex - 1] ? aThreads[iIndex - 1] : '';
|
||||||
|
aResult[4] = aThreads[iIndex + 1] ? aThreads[iIndex + 1] : '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return aResult;
|
||||||
|
|
||||||
|
}, this).extend({'notify': 'always'});
|
||||||
|
|
||||||
|
this.viewThreadsControlVisibility = ko.computed(function () {
|
||||||
|
return !!this.viewThreads.status()[0];
|
||||||
|
}, this);
|
||||||
|
|
||||||
|
this.viewThreadsControlDesc = ko.computed(function () {
|
||||||
|
return this.viewThreads.status()[1];
|
||||||
|
}, this);
|
||||||
|
|
||||||
|
this.viewThreadsControlBackAllow = ko.computed(function () {
|
||||||
|
return '' !== this.viewThreads.status()[4] && !this.messageLoadingThrottle();
|
||||||
|
}, this);
|
||||||
|
|
||||||
|
this.viewThreadsControlForwardAllow = ko.computed(function () {
|
||||||
|
return '' !== this.viewThreads.status()[3] && !this.messageLoadingThrottle();
|
||||||
|
}, this);
|
||||||
|
|
||||||
|
this.threadBackCommand = Utils.createCommand(this, function () {
|
||||||
|
var aStatus = this.viewThreads.status();
|
||||||
|
this.openThreadMessage(aStatus[4]);
|
||||||
|
}, this.viewThreadsControlBackAllow);
|
||||||
|
|
||||||
|
this.threadForwardCommand = Utils.createCommand(this, function () {
|
||||||
|
var aStatus = this.viewThreads.status();
|
||||||
|
this.openThreadMessage(aStatus[3]);
|
||||||
|
}, this.viewThreadsControlForwardAllow);
|
||||||
|
|
||||||
|
// PGP
|
||||||
this.viewPgpPassword = ko.observable('');
|
this.viewPgpPassword = ko.observable('');
|
||||||
this.viewPgpSignedVerifyStatus = ko.computed(function () {
|
this.viewPgpSignedVerifyStatus = ko.computed(function () {
|
||||||
return this.message() ? this.message().pgpSignedVerifyStatus() : Enums.SignedVerifyStatus.None;
|
return this.message() ? this.message().pgpSignedVerifyStatus() : Enums.SignedVerifyStatus.None;
|
||||||
|
|
@ -260,6 +352,8 @@
|
||||||
this.scrollMessageToTop();
|
this.scrollMessageToTop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.viewFolder = oMessage.folderFullNameRaw;
|
||||||
|
this.viewUid = oMessage.uid;
|
||||||
this.viewHash = oMessage.hash;
|
this.viewHash = oMessage.hash;
|
||||||
this.viewSubject(oMessage.subject());
|
this.viewSubject(oMessage.subject());
|
||||||
this.viewFromShort(oMessage.fromToLine(true, true));
|
this.viewFromShort(oMessage.fromToLine(true, true));
|
||||||
|
|
@ -277,6 +371,10 @@
|
||||||
this.viewViewLink(oMessage.viewLink());
|
this.viewViewLink(oMessage.viewLink());
|
||||||
this.viewDownloadLink(oMessage.downloadLink());
|
this.viewDownloadLink(oMessage.downloadLink());
|
||||||
this.viewIsImportant(oMessage.isImportant());
|
this.viewIsImportant(oMessage.isImportant());
|
||||||
|
this.viewIsFlagged(oMessage.flagged());
|
||||||
|
|
||||||
|
this.viewThreads(oMessage.threads());
|
||||||
|
this.viewThreads.trigger(!this.viewThreads.trigger());
|
||||||
|
|
||||||
sLastEmail = oMessage.fromAsSingleEmail();
|
sLastEmail = oMessage.fromAsSingleEmail();
|
||||||
Cache.getUserPic(sLastEmail, function (sPic, sEmail) {
|
Cache.getUserPic(sLastEmail, function (sPic, sEmail) {
|
||||||
|
|
@ -294,12 +392,29 @@
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
this.viewFolder = '';
|
||||||
|
this.viewUid = '';
|
||||||
this.viewHash = '';
|
this.viewHash = '';
|
||||||
|
|
||||||
|
this.viewThreads([]);
|
||||||
|
|
||||||
this.scrollMessageToTop();
|
this.scrollMessageToTop();
|
||||||
}
|
}
|
||||||
|
|
||||||
}, this);
|
}, this);
|
||||||
|
|
||||||
|
this.message.viewTrigger.subscribe(function () {
|
||||||
|
var oMessage = this.message();
|
||||||
|
if (oMessage)
|
||||||
|
{
|
||||||
|
this.viewIsFlagged(oMessage.flagged());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.viewIsFlagged(false);
|
||||||
|
}
|
||||||
|
}, this);
|
||||||
|
|
||||||
this.fullScreenMode.subscribe(function (bValue) {
|
this.fullScreenMode.subscribe(function (bValue) {
|
||||||
if (bValue)
|
if (bValue)
|
||||||
{
|
{
|
||||||
|
|
@ -333,6 +448,24 @@
|
||||||
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)
|
||||||
|
{
|
||||||
|
var oMessage = this.message();
|
||||||
|
if (oMessage && sUid)
|
||||||
|
{
|
||||||
|
MessageStore.selectThreadMessage(oMessage.folderFullNameRaw, sUid);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
MessageViewMailBoxUserView.prototype.isPgpActionVisible = function ()
|
MessageViewMailBoxUserView.prototype.isPgpActionVisible = function ()
|
||||||
{
|
{
|
||||||
return Enums.SignedVerifyStatus.Success !== this.viewPgpSignedVerifyStatus();
|
return Enums.SignedVerifyStatus.Success !== this.viewPgpSignedVerifyStatus();
|
||||||
|
|
@ -543,6 +676,9 @@
|
||||||
require('App/User').download(oAttachment.linkDownload());
|
require('App/User').download(oAttachment.linkDownload());
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
.on('click', '.messageItemHeader .flagParent', function () {
|
||||||
|
self.flagViewMessage();
|
||||||
|
})
|
||||||
;
|
;
|
||||||
|
|
||||||
this.message.focused.subscribe(function (bValue) {
|
this.message.focused.subscribe(function (bValue) {
|
||||||
|
|
@ -575,6 +711,19 @@
|
||||||
this.initShortcuts();
|
this.initShortcuts();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
MessageViewMailBoxUserView.prototype.flagViewMessage = function ()
|
||||||
|
{
|
||||||
|
var oMessage = this.message();
|
||||||
|
if (oMessage)
|
||||||
|
{
|
||||||
|
require('App/User').messageListAction(oMessage.folderFullNameRaw, oMessage.uid,
|
||||||
|
oMessage.flagged() ? Enums.MessageSetAction.UnsetFlag : Enums.MessageSetAction.SetFlag, [oMessage]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return {boolean}
|
* @return {boolean}
|
||||||
*/
|
*/
|
||||||
|
|
@ -664,16 +813,26 @@
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
key('ctrl+left, command+left, ctrl+up, command+up', Enums.KeyState.MessageView, function () {
|
key('ctrl+up, command+up', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () {
|
||||||
self.goUpCommand();
|
self.goUpCommand();
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
key('ctrl+right, command+right, ctrl+down, command+down', Enums.KeyState.MessageView, function () {
|
key('ctrl+down, command+down', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () {
|
||||||
self.goDownCommand();
|
self.goDownCommand();
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
key('ctrl+left, command+left', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () {
|
||||||
|
self.threadForwardCommand();
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
key('ctrl+right, command+right', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () {
|
||||||
|
self.threadBackCommand();
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
// print
|
// print
|
||||||
key('ctrl+p, command+p', Enums.KeyState.MessageView, function () {
|
key('ctrl+p, command+p', Enums.KeyState.MessageView, function () {
|
||||||
if (self.message())
|
if (self.message())
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ class Config
|
||||||
/**
|
/**
|
||||||
* @var int
|
* @var int
|
||||||
*/
|
*/
|
||||||
public static $LargeThreadLimit = 100;
|
public static $LargeThreadLimit = 50;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var bool
|
* @var bool
|
||||||
|
|
|
||||||
|
|
@ -698,6 +698,18 @@ class MailClient
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function GenerateImapClientHash()
|
||||||
|
{
|
||||||
|
return \md5('ImapClientHash/'.
|
||||||
|
$this->oImapClient->GetLogginedUser().'@'.
|
||||||
|
$this->oImapClient->GetConnectedHost().':'.
|
||||||
|
$this->oImapClient->GetConnectedPort()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $sFolder
|
* @param string $sFolder
|
||||||
* @param int $iCount
|
* @param int $iCount
|
||||||
|
|
@ -706,10 +718,12 @@ class MailClient
|
||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public static function GenerateHash($sFolder, $iCount, $iUnseenCount, $sUidNext)
|
public function GenerateFolderHash($sFolder, $iCount, $iUnseenCount, $sUidNext)
|
||||||
{
|
{
|
||||||
$iUnseenCount = 0; // unneccessery
|
$iUnseenCount = 0; // unneccessery
|
||||||
return \md5($sFolder.'-'.$iCount.'-'.$iUnseenCount.'-'.$sUidNext);
|
return \md5('FolderHash/'.$sFolder.'-'.$iCount.'-'.$iUnseenCount.'-'.$sUidNext.'-'.
|
||||||
|
$this->GenerateImapClientHash()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -837,7 +851,7 @@ class MailClient
|
||||||
|
|
||||||
$aResult = array(
|
$aResult = array(
|
||||||
'Folder' => $sFolderName,
|
'Folder' => $sFolderName,
|
||||||
'Hash' => self::GenerateHash($sFolderName, $iCount, $iUnseenCount, $sUidNext),
|
'Hash' => $this->GenerateFolderHash($sFolderName, $iCount, $iUnseenCount, $sUidNext),
|
||||||
'MessageCount' => $iCount,
|
'MessageCount' => $iCount,
|
||||||
'MessageUnseenCount' => $iUnseenCount,
|
'MessageUnseenCount' => $iUnseenCount,
|
||||||
'UidNext' => $sUidNext,
|
'UidNext' => $sUidNext,
|
||||||
|
|
@ -866,7 +880,7 @@ class MailClient
|
||||||
|
|
||||||
$this->initFolderValues($sFolderName, $iCount, $iUnseenCount, $sUidNext);
|
$this->initFolderValues($sFolderName, $iCount, $iUnseenCount, $sUidNext);
|
||||||
|
|
||||||
return self::GenerateHash($sFolderName, $iCount, $iUnseenCount, $sUidNext);
|
return $this->GenerateFolderHash($sFolderName, $iCount, $iUnseenCount, $sUidNext);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -1410,7 +1424,8 @@ class MailClient
|
||||||
* @param string $sFolderHash
|
* @param string $sFolderHash
|
||||||
* @param array $aIndexOrUids
|
* @param array $aIndexOrUids
|
||||||
* @param \MailSo\Cache\CacheClient $oCacher
|
* @param \MailSo\Cache\CacheClient $oCacher
|
||||||
* @param int $iThreadLimit = 100
|
* @param int $iThreadLimit = 50
|
||||||
|
* @param bool $bCacheOnly = false
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*
|
*
|
||||||
|
|
@ -1418,7 +1433,7 @@ class MailClient
|
||||||
* @throws \MailSo\Net\Exceptions\Exception
|
* @throws \MailSo\Net\Exceptions\Exception
|
||||||
* @throws \MailSo\Imap\Exceptions\Exception
|
* @throws \MailSo\Imap\Exceptions\Exception
|
||||||
*/
|
*/
|
||||||
public function MessageListThreadsMap($sFolderName, $sFolderHash, $aIndexOrUids, $oCacher, $iThreadLimit = 100)
|
public function MessageListThreadsMap($sFolderName, $sFolderHash, $aIndexOrUids, $oCacher, $iThreadLimit = 50, $bCacheOnly = false)
|
||||||
{
|
{
|
||||||
$iThreadLimit = \is_int($iThreadLimit) && 0 < $iThreadLimit ? $iThreadLimit : 0;
|
$iThreadLimit = \is_int($iThreadLimit) && 0 < $iThreadLimit ? $iThreadLimit : 0;
|
||||||
|
|
||||||
|
|
@ -1438,30 +1453,36 @@ class MailClient
|
||||||
|
|
||||||
if ($oCacher && $oCacher->IsInited())
|
if ($oCacher && $oCacher->IsInited())
|
||||||
{
|
{
|
||||||
$sSerializedHash =
|
$sSerializedHashKey =
|
||||||
'ThreadsMapSorted/'.$sSearchHash.'/'.
|
'ThreadsMapSorted/'.$sSearchHash.'/'.
|
||||||
'Limit='.$iThreadLimit.'/'.
|
'Limit='.$iThreadLimit.'/'.$sFolderName.'/'.$sFolderHash;
|
||||||
$this->oImapClient->GetLogginedUser().'@'.
|
|
||||||
$this->oImapClient->GetConnectedHost().':'.
|
|
||||||
$this->oImapClient->GetConnectedPort().'/'.
|
|
||||||
$sFolderName.'/'.$sFolderHash;
|
|
||||||
|
|
||||||
$sSerializedUids = $oCacher->Get($sSerializedHash);
|
if ($this->oLogger)
|
||||||
|
{
|
||||||
|
$this->oLogger->Write($sSerializedHashKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
$sSerializedUids = $oCacher->Get($sSerializedHashKey);
|
||||||
if (!empty($sSerializedUids))
|
if (!empty($sSerializedUids))
|
||||||
{
|
{
|
||||||
$aSerializedUids = @\unserialize($sSerializedUids);
|
$aSerializedUids = @\json_decode($sSerializedUids, true);
|
||||||
if (is_array($aSerializedUids))
|
if (isset($aSerializedUids['ThreadsUids']) && \is_array($aSerializedUids['ThreadsUids']))
|
||||||
{
|
{
|
||||||
if ($this->oLogger)
|
if ($this->oLogger)
|
||||||
{
|
{
|
||||||
$this->oLogger->Write('Get Serialized Thread UIDS from cache ("'.$sFolderName.'" / '.$sSearchHash.') [count:'.\count($aSerializedUids).']');
|
$this->oLogger->Write('Get Serialized Thread UIDS from cache ("'.$sFolderName.'" / '.$sSearchHash.') [count:'.\count($aSerializedUids['ThreadsUids']).']');
|
||||||
}
|
}
|
||||||
|
|
||||||
return $aSerializedUids;
|
return $aSerializedUids['ThreadsUids'];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($bCacheOnly)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
$this->oImapClient->FolderExamine($sFolderName);
|
$this->oImapClient->FolderExamine($sFolderName);
|
||||||
|
|
||||||
$aThreadUids = array();
|
$aThreadUids = array();
|
||||||
|
|
@ -1471,6 +1492,7 @@ class MailClient
|
||||||
}
|
}
|
||||||
catch (\MailSo\Imap\Exceptions\RuntimeException $oException)
|
catch (\MailSo\Imap\Exceptions\RuntimeException $oException)
|
||||||
{
|
{
|
||||||
|
unset($oException);
|
||||||
$aThreadUids = array();
|
$aThreadUids = array();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1582,9 +1604,11 @@ class MailClient
|
||||||
$aResult = $aLastResult;
|
$aResult = $aLastResult;
|
||||||
unset($aLastResult);
|
unset($aLastResult);
|
||||||
|
|
||||||
if ($oCacher && $oCacher->IsInited() && !empty($sSerializedHash))
|
if ($oCacher && $oCacher->IsInited() && !empty($sSerializedHashKey))
|
||||||
{
|
{
|
||||||
$oCacher->Set($sSerializedHash, serialize($aResult));
|
$oCacher->Set($sSerializedHashKey, @\json_encode(array(
|
||||||
|
'ThreadsUids' => $aResult
|
||||||
|
)));
|
||||||
|
|
||||||
if ($this->oLogger)
|
if ($this->oLogger)
|
||||||
{
|
{
|
||||||
|
|
@ -1668,8 +1692,8 @@ class MailClient
|
||||||
private function getSearchUidsResult($sSearch, $sFolderName, $sFolderHash,
|
private function getSearchUidsResult($sSearch, $sFolderName, $sFolderHash,
|
||||||
$bUseSortIfSupported = true, $bUseESearchOrESortRequest = false, $oCacher = null)
|
$bUseSortIfSupported = true, $bUseESearchOrESortRequest = false, $oCacher = null)
|
||||||
{
|
{
|
||||||
$bUidsFromCacher = false;
|
|
||||||
$aResultUids = false;
|
$aResultUids = false;
|
||||||
|
$bUidsFromCacher = false;
|
||||||
$bUseCacheAfterSearch = true;
|
$bUseCacheAfterSearch = true;
|
||||||
$sSerializedHash = '';
|
$sSerializedHash = '';
|
||||||
|
|
||||||
|
|
@ -1680,23 +1704,21 @@ class MailClient
|
||||||
$sSearchCriterias = $this->getImapSearchCriterias($sSearch, 0, $bUseCacheAfterSearch);
|
$sSearchCriterias = $this->getImapSearchCriterias($sSearch, 0, $bUseCacheAfterSearch);
|
||||||
if ($bUseCacheAfterSearch && $oCacher && $oCacher->IsInited())
|
if ($bUseCacheAfterSearch && $oCacher && $oCacher->IsInited())
|
||||||
{
|
{
|
||||||
$sSerializedHash =
|
$sSerializedHash = 'SearchSortUids/'.
|
||||||
($bUseSortIfSupported ? 'S': 'N').'/'.
|
($bUseSortIfSupported ? 'S': 'N').'/'.
|
||||||
$this->oImapClient->GetLogginedUser().'@'.
|
$this->GenerateImapClientHash().'/'.
|
||||||
$this->oImapClient->GetConnectedHost().':'.
|
$sFolderName.'/'.$sSearchCriterias;
|
||||||
$this->oImapClient->GetConnectedPort().'/'.
|
|
||||||
$sFolderName.'/'.
|
|
||||||
$sSearchCriterias;
|
|
||||||
|
|
||||||
$sSerializedLog = '"'.$sFolderName.'" / '.$sSearchCriterias.'';
|
$sSerializedLog = '"'.$sFolderName.'" / '.$sSearchCriterias.'';
|
||||||
|
|
||||||
$sSerialized = $oCacher->Get($sSerializedHash);
|
$sSerialized = $oCacher->Get($sSerializedHash);
|
||||||
if (!empty($sSerialized))
|
if (!empty($sSerialized))
|
||||||
{
|
{
|
||||||
$aSerialized = @\unserialize($sSerialized);
|
$aSerialized = @\json_decode($sSerialized, true);
|
||||||
if (\is_array($aSerialized) && isset($aSerialized['FolderHash'], $aSerialized['Uids']) &&
|
if (\is_array($aSerialized) && isset($aSerialized['FolderHash'], $aSerialized['Uids']) &&
|
||||||
\is_array($aSerialized['Uids']) &&
|
$sFolderHash === $aSerialized['FolderHash'] &&
|
||||||
($sFolderHash === $aSerialized['FolderHash']))
|
\is_array($aSerialized['Uids'])
|
||||||
|
)
|
||||||
{
|
{
|
||||||
if ($this->oLogger)
|
if ($this->oLogger)
|
||||||
{
|
{
|
||||||
|
|
@ -1779,7 +1801,7 @@ class MailClient
|
||||||
|
|
||||||
if (!$bUidsFromCacher && $bUseCacheAfterSearch && \is_array($aResultUids) && $oCacher && $oCacher->IsInited() && 0 < \strlen($sSerializedHash))
|
if (!$bUidsFromCacher && $bUseCacheAfterSearch && \is_array($aResultUids) && $oCacher && $oCacher->IsInited() && 0 < \strlen($sSerializedHash))
|
||||||
{
|
{
|
||||||
$oCacher->Set($sSerializedHash, \serialize(array(
|
$oCacher->Set($sSerializedHash, @\json_encode(array(
|
||||||
'FolderHash' => $sFolderHash,
|
'FolderHash' => $sFolderHash,
|
||||||
'Uids' => $aResultUids
|
'Uids' => $aResultUids
|
||||||
)));
|
)));
|
||||||
|
|
@ -1794,6 +1816,54 @@ class MailClient
|
||||||
return $aResultUids;
|
return $aResultUids;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $sFolderName
|
||||||
|
* @param string $sFolderHash
|
||||||
|
* @param string $sUid
|
||||||
|
* @param \MailSo\Cache\CacheClient|null $oCacher = null
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function MessageThreadUidsFromCache($sFolderName, $sFolderHash, $sUid, $oCacher = null)
|
||||||
|
{
|
||||||
|
$aResult = array();
|
||||||
|
if (0 < \strlen($sFolderName) && 0 < \strlen($sFolderHash) && 0 < \strlen($sUid) && $oCacher && $oCacher->IsInited())
|
||||||
|
{
|
||||||
|
$mThreads = $this->MessageListThreadsMap($sFolderName, $sFolderHash, array(), $oCacher,
|
||||||
|
\MailSo\Config::$LargeThreadLimit, true);
|
||||||
|
|
||||||
|
if (\is_array($mThreads))
|
||||||
|
{
|
||||||
|
$iUid = (int) $sUid;
|
||||||
|
foreach ($mThreads as $iSubUid => $aSubUids)
|
||||||
|
{
|
||||||
|
if ($iUid === $iSubUid)
|
||||||
|
{
|
||||||
|
$aResult = $aSubUids;
|
||||||
|
if (!\is_array($aResult))
|
||||||
|
{
|
||||||
|
$aResult = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
\array_unshift($aResult, $iSubUid);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (\is_array($aSubUids))
|
||||||
|
{
|
||||||
|
if (\in_array($iUid, $aSubUids))
|
||||||
|
{
|
||||||
|
$aResult = $aSubUids;
|
||||||
|
\array_unshift($aResult, $iSubUid);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return \array_map('trim', $aResult);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $sFolderName
|
* @param string $sFolderName
|
||||||
* @param int $iOffset = 0
|
* @param int $iOffset = 0
|
||||||
|
|
@ -1803,7 +1873,6 @@ class MailClient
|
||||||
* @param \MailSo\Cache\CacheClient|null $oCacher = null
|
* @param \MailSo\Cache\CacheClient|null $oCacher = null
|
||||||
* @param bool $bUseSortIfSupported = false
|
* @param bool $bUseSortIfSupported = false
|
||||||
* @param bool $bUseThreadSortIfSupported = false
|
* @param bool $bUseThreadSortIfSupported = false
|
||||||
* @param array $aExpandedThreadsUids = array()
|
|
||||||
* @param bool $bUseESearchOrESortRequest = false
|
* @param bool $bUseESearchOrESortRequest = false
|
||||||
*
|
*
|
||||||
* @return \MailSo\Mail\MessageCollection
|
* @return \MailSo\Mail\MessageCollection
|
||||||
|
|
@ -1812,9 +1881,8 @@ class MailClient
|
||||||
* @throws \MailSo\Net\Exceptions\Exception
|
* @throws \MailSo\Net\Exceptions\Exception
|
||||||
* @throws \MailSo\Imap\Exceptions\Exception
|
* @throws \MailSo\Imap\Exceptions\Exception
|
||||||
*/
|
*/
|
||||||
public function MessageList($sFolderName, $iOffset = 0, $iLimit = 10, $sSearch = '', $sPrevUidNext = '',
|
public function MessageList($sFolderName, $iOffset = 0, $iLimit = 10, $sSearch = '', $sPrevUidNext = '', $oCacher = null,
|
||||||
$oCacher = null, $bUseSortIfSupported = false, $bUseThreadSortIfSupported = false,
|
$bUseSortIfSupported = false, $bUseThreadSortIfSupported = false, $bUseESearchOrESortRequest = false)
|
||||||
$aExpandedThreadsUids = array(), $bUseESearchOrESortRequest = false)
|
|
||||||
{
|
{
|
||||||
$sSearch = \trim($sSearch);
|
$sSearch = \trim($sSearch);
|
||||||
if (!\MailSo\Base\Validator::RangeInt($iOffset, 0) ||
|
if (!\MailSo\Base\Validator::RangeInt($iOffset, 0) ||
|
||||||
|
|
@ -1831,8 +1899,6 @@ class MailClient
|
||||||
$oMessageCollection->Limit = $iLimit;
|
$oMessageCollection->Limit = $iLimit;
|
||||||
$oMessageCollection->Search = $sSearch;
|
$oMessageCollection->Search = $sSearch;
|
||||||
|
|
||||||
$aLastCollapsedThreadUids = array();
|
|
||||||
|
|
||||||
$aThreads = array();
|
$aThreads = array();
|
||||||
|
|
||||||
$iMessageCount = 0;
|
$iMessageCount = 0;
|
||||||
|
|
@ -1853,7 +1919,7 @@ class MailClient
|
||||||
$this->initFolderValues($sFolderName, $iMessageRealCount, $iMessageUnseenCount, $sUidNext);
|
$this->initFolderValues($sFolderName, $iMessageRealCount, $iMessageUnseenCount, $sUidNext);
|
||||||
$iMessageCount = $iMessageRealCount;
|
$iMessageCount = $iMessageRealCount;
|
||||||
|
|
||||||
$oMessageCollection->FolderHash = self::GenerateHash($sFolderName, $iMessageRealCount, $iMessageUnseenCount, $sUidNext);
|
$oMessageCollection->FolderHash = $this->GenerateFolderHash($sFolderName, $iMessageRealCount, $iMessageUnseenCount, $sUidNext);
|
||||||
$oMessageCollection->UidNext = $sUidNext;
|
$oMessageCollection->UidNext = $sUidNext;
|
||||||
$oMessageCollection->NewMessages = $this->getFolderNextMessageInformation($sFolderName, $sPrevUidNext, $sUidNext);
|
$oMessageCollection->NewMessages = $this->getFolderNextMessageInformation($sFolderName, $sPrevUidNext, $sUidNext);
|
||||||
|
|
||||||
|
|
@ -1889,11 +1955,9 @@ class MailClient
|
||||||
$oMessageCollection->FolderName, $oMessageCollection->FolderHash,
|
$oMessageCollection->FolderName, $oMessageCollection->FolderHash,
|
||||||
$bUseSortIfSupported, $bUseESearchOrESortRequest, $oCacher);
|
$bUseSortIfSupported, $bUseESearchOrESortRequest, $oCacher);
|
||||||
|
|
||||||
$aThreads = $this->MessageListThreadsMap($oMessageCollection->FolderName, $oMessageCollection->FolderHash, $aIndexOrUids,
|
$aThreads = $this->MessageListThreadsMap(
|
||||||
$oCacher, \MailSo\Config::$LargeThreadLimit);
|
$oMessageCollection->FolderName, $oMessageCollection->FolderHash,
|
||||||
|
$aIndexOrUids, $oCacher, \MailSo\Config::$LargeThreadLimit);
|
||||||
$aExpandedThreadsUids = \is_array($aExpandedThreadsUids) ? $aExpandedThreadsUids : array();
|
|
||||||
$bWatchExpanded = 0 < \count($aExpandedThreadsUids);
|
|
||||||
|
|
||||||
$aNewIndexOrUids = array();
|
$aNewIndexOrUids = array();
|
||||||
foreach ($aIndexOrUids as $iUid)
|
foreach ($aIndexOrUids as $iUid)
|
||||||
|
|
@ -1901,21 +1965,6 @@ class MailClient
|
||||||
if (isset($aThreads[$iUid]))
|
if (isset($aThreads[$iUid]))
|
||||||
{
|
{
|
||||||
$aNewIndexOrUids[] = $iUid;
|
$aNewIndexOrUids[] = $iUid;
|
||||||
if (\is_array($aThreads[$iUid]))
|
|
||||||
{
|
|
||||||
if ($bWatchExpanded && \in_array($iUid, $aExpandedThreadsUids))
|
|
||||||
{
|
|
||||||
$aSubArray = $aThreads[$iUid];
|
|
||||||
foreach ($aSubArray as $iSubRootUid)
|
|
||||||
{
|
|
||||||
$aNewIndexOrUids[] = $iSubRootUid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$aLastCollapsedThreadUids[] = $iUid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1966,38 +2015,20 @@ class MailClient
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$aLastCollapsedThreadUidsForPage = array();
|
|
||||||
|
|
||||||
if (!$bSearch && $bUseThreadSortIfSupported && 0 < \count($aThreads))
|
if (!$bSearch && $bUseThreadSortIfSupported && 0 < \count($aThreads))
|
||||||
{
|
{
|
||||||
$oMessageCollection->ForeachList(function (/* @var $oMessage \MailSo\Mail\Message */ $oMessage) use (
|
$oMessageCollection->ForeachList(function (/* @var $oMessage \MailSo\Mail\Message */ $oMessage) use ($aThreads) {
|
||||||
$aThreads, $aLastCollapsedThreadUids, &$aLastCollapsedThreadUidsForPage)
|
|
||||||
{
|
|
||||||
$iUid = $oMessage->Uid();
|
|
||||||
if (\in_array($iUid, $aLastCollapsedThreadUids))
|
|
||||||
{
|
|
||||||
$aLastCollapsedThreadUidsForPage[] = $iUid;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
$iUid = $oMessage->Uid();
|
||||||
if (isset($aThreads[$iUid]) && \is_array($aThreads[$iUid]) && 0 < \count($aThreads[$iUid]))
|
if (isset($aThreads[$iUid]) && \is_array($aThreads[$iUid]) && 0 < \count($aThreads[$iUid]))
|
||||||
{
|
{
|
||||||
$oMessage->SetThreads($aThreads[$iUid]);
|
$aSubThreads = $aThreads[$iUid];
|
||||||
$oMessage->SetThreadsLen(\count($aThreads[$iUid]));
|
\array_unshift($aSubThreads, $iUid);
|
||||||
}
|
|
||||||
else if (!isset($aThreads[$iUid]))
|
$oMessage->SetThreads(\array_map('trim', $aSubThreads));
|
||||||
{
|
unset($aSubThreads);
|
||||||
foreach ($aThreads as $iKeyUid => $mSubItem)
|
|
||||||
{
|
|
||||||
if (\is_array($mSubItem) && \in_array($iUid, $mSubItem))
|
|
||||||
{
|
|
||||||
$oMessage->SetParentThread($iKeyUid);
|
|
||||||
$oMessage->SetThreadsLen(\count($mSubItem));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$oMessageCollection->LastCollapsedThreadUids = $aLastCollapsedThreadUidsForPage;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $oMessageCollection;
|
return $oMessageCollection;
|
||||||
|
|
|
||||||
|
|
@ -162,16 +162,6 @@ class Message
|
||||||
*/
|
*/
|
||||||
private $aThreads;
|
private $aThreads;
|
||||||
|
|
||||||
/**
|
|
||||||
* @var int
|
|
||||||
*/
|
|
||||||
private $iParentThread;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @var int
|
|
||||||
*/
|
|
||||||
private $iThreadsLen;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var bool
|
* @var bool
|
||||||
*/
|
*/
|
||||||
|
|
@ -240,8 +230,6 @@ class Message
|
||||||
$this->sReadReceipt = '';
|
$this->sReadReceipt = '';
|
||||||
|
|
||||||
$this->aThreads = array();
|
$this->aThreads = array();
|
||||||
$this->iThreadsLen = 0;
|
|
||||||
$this->iParentThread = 0;
|
|
||||||
|
|
||||||
$this->bTextPartIsTrimmed = false;
|
$this->bTextPartIsTrimmed = false;
|
||||||
|
|
||||||
|
|
@ -542,38 +530,6 @@ class Message
|
||||||
$this->aThreads = \is_array($aThreads) ? $aThreads : array();
|
$this->aThreads = \is_array($aThreads) ? $aThreads : array();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
public function ThreadsLen()
|
|
||||||
{
|
|
||||||
return $this->iThreadsLen;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param int $iThreadsLen
|
|
||||||
*/
|
|
||||||
public function SetThreadsLen($iThreadsLen)
|
|
||||||
{
|
|
||||||
$this->iThreadsLen = $iThreadsLen;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return int
|
|
||||||
*/
|
|
||||||
public function ParentThread()
|
|
||||||
{
|
|
||||||
return $this->iParentThread;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param int $iParentThread
|
|
||||||
*/
|
|
||||||
public function SetParentThread($iParentThread)
|
|
||||||
{
|
|
||||||
$this->iParentThread = $iParentThread;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return boole
|
* @return boole
|
||||||
*/
|
*/
|
||||||
|
|
@ -664,7 +620,8 @@ class Message
|
||||||
$this->oDeliveredTo = $oHeaders->GetAsEmailCollection(\MailSo\Mime\Enumerations\Header::DELIVERED_TO, $bCharsetAutoDetect);
|
$this->oDeliveredTo = $oHeaders->GetAsEmailCollection(\MailSo\Mime\Enumerations\Header::DELIVERED_TO, $bCharsetAutoDetect);
|
||||||
|
|
||||||
$this->sInReplyTo = $oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::IN_REPLY_TO);
|
$this->sInReplyTo = $oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::IN_REPLY_TO);
|
||||||
$this->sReferences = $oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::REFERENCES);
|
$this->sReferences = \trim(\preg_replace('/[\s]+/', ' ',
|
||||||
|
$oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::REFERENCES)));
|
||||||
|
|
||||||
$sHeaderDate = $oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::DATE);
|
$sHeaderDate = $oHeaders->ValueByName(\MailSo\Mime\Enumerations\Header::DATE);
|
||||||
$this->sHeaderDate = $sHeaderDate;
|
$this->sHeaderDate = $sHeaderDate;
|
||||||
|
|
|
||||||
|
|
@ -256,7 +256,8 @@ class Message
|
||||||
*/
|
*/
|
||||||
public function SetReferences($sReferences)
|
public function SetReferences($sReferences)
|
||||||
{
|
{
|
||||||
$this->aHeadersValue[\MailSo\Mime\Enumerations\Header::REFERENCES] = $sReferences;
|
$this->aHeadersValue[\MailSo\Mime\Enumerations\Header::REFERENCES] =
|
||||||
|
\trim(\preg_replace('/[\s]+/', ' ', $sReferences));
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5363,6 +5363,45 @@ class Actions
|
||||||
return $this->DefaultResponse(__FUNCTION__, $aResult);
|
return $this->DefaultResponse(__FUNCTION__, $aResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
*
|
||||||
|
* @throws \MailSo\Base\Exceptions\Exception
|
||||||
|
*/
|
||||||
|
public function DoMessageThreadsFromCache()
|
||||||
|
{
|
||||||
|
$sFolder = $this->GetActionParam('Folder', '');
|
||||||
|
$sFolderHash = $this->GetActionParam('FolderHash', '');
|
||||||
|
$sUid = (string) $this->GetActionParam('Uid', '');
|
||||||
|
|
||||||
|
if (0 === \strlen($sFolder) || 0 === \strlen($sUid))
|
||||||
|
{
|
||||||
|
throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::InvalidInputArgument);
|
||||||
|
}
|
||||||
|
|
||||||
|
$aResult = array(
|
||||||
|
'Folder' => $sFolder,
|
||||||
|
'Uid' => $sUid,
|
||||||
|
'FolderHash' => $sFolderHash,
|
||||||
|
'ThreadUids' => null
|
||||||
|
);
|
||||||
|
|
||||||
|
$oCache = $this->cacherForUids();
|
||||||
|
if ($oCache && $this->Config()->Get('labs', 'use_imap_thread', false))
|
||||||
|
{
|
||||||
|
$aThreadUids = $this->MailClient()->MessageThreadUidsFromCache(
|
||||||
|
$sFolder, $sFolderHash, $sUid, $oCache
|
||||||
|
);
|
||||||
|
|
||||||
|
if (\is_array($aThreadUids) && 1 < \count($aThreadUids))
|
||||||
|
{
|
||||||
|
$aResult['ThreadUids'] = $aThreadUids;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->DefaultResponse(__FUNCTION__, $aResult);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return array
|
* @return array
|
||||||
*
|
*
|
||||||
|
|
@ -5379,7 +5418,6 @@ class Actions
|
||||||
$sSearch = '';
|
$sSearch = '';
|
||||||
$sUidNext = '';
|
$sUidNext = '';
|
||||||
$bUseThreads = false;
|
$bUseThreads = false;
|
||||||
$sExpandedThreadUid = '';
|
|
||||||
|
|
||||||
$sRawKey = $this->GetActionParam('RawKey', '');
|
$sRawKey = $this->GetActionParam('RawKey', '');
|
||||||
$aValues = $this->getDecodedClientRawKeyValue($sRawKey, 9);
|
$aValues = $this->getDecodedClientRawKeyValue($sRawKey, 9);
|
||||||
|
|
@ -5392,7 +5430,6 @@ class Actions
|
||||||
$sSearch = (string) $aValues[3];
|
$sSearch = (string) $aValues[3];
|
||||||
$sUidNext = (string) $aValues[6];
|
$sUidNext = (string) $aValues[6];
|
||||||
$bUseThreads = (bool) $aValues[7];
|
$bUseThreads = (bool) $aValues[7];
|
||||||
$sExpandedThreadUid = (string) $aValues[8];
|
|
||||||
|
|
||||||
$this->verifyCacheByKey($sRawKey);
|
$this->verifyCacheByKey($sRawKey);
|
||||||
}
|
}
|
||||||
|
|
@ -5404,7 +5441,6 @@ class Actions
|
||||||
$sSearch = $this->GetActionParam('Search', '');
|
$sSearch = $this->GetActionParam('Search', '');
|
||||||
$sUidNext = $this->GetActionParam('UidNext', '');
|
$sUidNext = $this->GetActionParam('UidNext', '');
|
||||||
$bUseThreads = '1' === (string) $this->GetActionParam('UseThreads', '0');
|
$bUseThreads = '1' === (string) $this->GetActionParam('UseThreads', '0');
|
||||||
$sExpandedThreadUid = (string) $this->GetActionParam('ExpandedThreadUid', '');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (0 === strlen($sFolder))
|
if (0 === strlen($sFolder))
|
||||||
|
|
@ -5419,29 +5455,13 @@ class Actions
|
||||||
if (!$this->Config()->Get('labs', 'use_imap_thread', false))
|
if (!$this->Config()->Get('labs', 'use_imap_thread', false))
|
||||||
{
|
{
|
||||||
$bUseThreads = false;
|
$bUseThreads = false;
|
||||||
$sExpandedThreadUid = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
$aExpandedThreadUid = array();
|
|
||||||
if (0 < \strlen($sExpandedThreadUid))
|
|
||||||
{
|
|
||||||
$aExpandedThreadUid = \explode(',', $sExpandedThreadUid);
|
|
||||||
|
|
||||||
$aExpandedThreadUid = \array_map(function ($sValue) {
|
|
||||||
$sValue = \trim($sValue);
|
|
||||||
return \is_numeric($sValue) ? (int) $sValue : 0;
|
|
||||||
}, $aExpandedThreadUid);
|
|
||||||
|
|
||||||
$aExpandedThreadUid = \array_filter($aExpandedThreadUid, function ($iValue) {
|
|
||||||
return 0 < $iValue;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$oMessageList = $this->MailClient()->MessageList(
|
$oMessageList = $this->MailClient()->MessageList(
|
||||||
$sFolder, $iOffset, $iLimit, $sSearch, $sUidNext,
|
$sFolder, $iOffset, $iLimit, $sSearch, $sUidNext,
|
||||||
$this->cacherForUids(),
|
$this->cacherForUids(),
|
||||||
!!$this->Config()->Get('labs', 'use_imap_sort', false),
|
!!$this->Config()->Get('labs', 'use_imap_sort', false),
|
||||||
$bUseThreads, $aExpandedThreadUid,
|
$bUseThreads,
|
||||||
!!$this->Config()->Get('labs', 'use_imap_esearch_esort', false)
|
!!$this->Config()->Get('labs', 'use_imap_esearch_esort', false)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -8875,8 +8895,6 @@ class Actions
|
||||||
'DeliveredTo' => $this->responseObject($mResponse->DeliveredTo(), $sParent, $aParameters),
|
'DeliveredTo' => $this->responseObject($mResponse->DeliveredTo(), $sParent, $aParameters),
|
||||||
'Priority' => $mResponse->Priority(),
|
'Priority' => $mResponse->Priority(),
|
||||||
'Threads' => $mResponse->Threads(),
|
'Threads' => $mResponse->Threads(),
|
||||||
'ThreadsLen' => $mResponse->ThreadsLen(),
|
|
||||||
'ParentThread' => $mResponse->ParentThread(),
|
|
||||||
'Sensitivity' => $mResponse->Sensitivity(),
|
'Sensitivity' => $mResponse->Sensitivity(),
|
||||||
'ExternalProxy' => false,
|
'ExternalProxy' => false,
|
||||||
'ReadReceipt' => ''
|
'ReadReceipt' => ''
|
||||||
|
|
@ -9149,7 +9167,7 @@ class Actions
|
||||||
'MessageCount' => (int) $mStatus['MESSAGES'],
|
'MessageCount' => (int) $mStatus['MESSAGES'],
|
||||||
'MessageUnseenCount' => (int) $mStatus['UNSEEN'],
|
'MessageUnseenCount' => (int) $mStatus['UNSEEN'],
|
||||||
'UidNext' => (string) $mStatus['UIDNEXT'],
|
'UidNext' => (string) $mStatus['UIDNEXT'],
|
||||||
'Hash' => \MailSo\Mail\MailClient::GenerateHash(
|
'Hash' => $this->MailClient()->GenerateFolderHash(
|
||||||
$mResponse->FullNameRaw(), $mStatus['MESSAGES'], $mStatus['UNSEEN'], $mStatus['UIDNEXT'])
|
$mResponse->FullNameRaw(), $mStatus['MESSAGES'], $mStatus['UNSEEN'], $mStatus['UIDNEXT'])
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -9179,7 +9197,7 @@ class Actions
|
||||||
'FolderHash' => $mResponse->FolderHash,
|
'FolderHash' => $mResponse->FolderHash,
|
||||||
'UidNext' => $mResponse->UidNext,
|
'UidNext' => $mResponse->UidNext,
|
||||||
'NewMessages' => $this->responseObject($mResponse->NewMessages),
|
'NewMessages' => $this->responseObject($mResponse->NewMessages),
|
||||||
'LastCollapsedThreadUids' => $mResponse->LastCollapsedThreadUids,
|
// 'LastCollapsedThreadUids' => $mResponse->LastCollapsedThreadUids,
|
||||||
'Offset' => $mResponse->Offset,
|
'Offset' => $mResponse->Offset,
|
||||||
'Limit' => $mResponse->Limit,
|
'Limit' => $mResponse->Limit,
|
||||||
'Search' => $mResponse->Search
|
'Search' => $mResponse->Search
|
||||||
|
|
|
||||||
|
|
@ -92,7 +92,7 @@ class Api
|
||||||
(int) \RainLoop\Api::Config()->Get('labs', 'imap_message_list_date_filter', 0);
|
(int) \RainLoop\Api::Config()->Get('labs', 'imap_message_list_date_filter', 0);
|
||||||
|
|
||||||
\MailSo\Config::$LargeThreadLimit =
|
\MailSo\Config::$LargeThreadLimit =
|
||||||
(int) \RainLoop\Api::Config()->Get('labs', 'imap_large_thread_limit', 100);
|
(int) \RainLoop\Api::Config()->Get('labs', 'imap_large_thread_limit', 50);
|
||||||
|
|
||||||
\MailSo\Config::$SystemLogger = \RainLoop\Api::Logger();
|
\MailSo\Config::$SystemLogger = \RainLoop\Api::Logger();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -291,7 +291,7 @@ Enables caching in the system'),
|
||||||
'imap_message_list_fast_simple_search' => array(true),
|
'imap_message_list_fast_simple_search' => array(true),
|
||||||
'imap_message_list_count_limit_trigger' => array(0),
|
'imap_message_list_count_limit_trigger' => array(0),
|
||||||
'imap_message_list_date_filter' => array(0),
|
'imap_message_list_date_filter' => array(0),
|
||||||
'imap_large_thread_limit' => array(100),
|
'imap_large_thread_limit' => array(50),
|
||||||
'imap_folder_list_limit' => array(200),
|
'imap_folder_list_limit' => array(200),
|
||||||
'imap_show_login_alert' => array(true),
|
'imap_show_login_alert' => array(true),
|
||||||
'smtp_show_server_errors' => array(false),
|
'smtp_show_server_errors' => array(false),
|
||||||
|
|
|
||||||
|
|
@ -22,13 +22,12 @@
|
||||||
<i class="checkboxMessage" data-bind="css: checked() ? 'checkboxMessage icon-checkbox-checked' : 'checkboxMessage icon-checkbox-unchecked'"></i>
|
<i class="checkboxMessage" data-bind="css: checked() ? 'checkboxMessage icon-checkbox-checked' : 'checkboxMessage icon-checkbox-unchecked'"></i>
|
||||||
</div>
|
</div>
|
||||||
<div class="senderParent actionHandle dragHandle">
|
<div class="senderParent actionHandle dragHandle">
|
||||||
<span class="threadsCountParent fullThreadHandle" data-bind="visible: '' !== threadsLenResult(), css: { 'lastSelected': !lastInCollapsedThread() }">
|
|
||||||
<span lass="threadsCount" data-bind="visible: !lastInCollapsedThreadLoading(), text: threadsLenResult"></span>
|
|
||||||
<span lass="threadsCount" data-bind="visible: lastInCollapsedThreadLoading()">x</span>
|
|
||||||
</span>
|
|
||||||
<span class="replyFlag"><i class="icon-reply"></i> </span>
|
<span class="replyFlag"><i class="icon-reply"></i> </span>
|
||||||
<span class="forwardFlag"><i class="icon-forward"></i> </span>
|
<span class="forwardFlag"><i class="icon-forward"></i> </span>
|
||||||
<span class="sender" data-bind="text: senderEmailsString, attr: {'title': senderClearEmailsString}"></span>
|
<span class="sender" data-bind="text: senderEmailsString, attr: {'title': senderClearEmailsString}"></span>
|
||||||
|
<span class="thre" data-bind="visible: 1 < threadsLen()">
|
||||||
|
(<span data-bind="text: threadsLen"></span>)
|
||||||
|
</span>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="attachmentParent actionHandle dragHandle">
|
<div class="attachmentParent actionHandle dragHandle">
|
||||||
|
|
|
||||||
|
|
@ -22,13 +22,12 @@
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="senderParent actionHandle dragHandle">
|
<div class="senderParent actionHandle dragHandle">
|
||||||
<span class="threadsCountParent fullThreadHandle" data-bind="visible: '' !== threadsLenResult(), css: { 'lastSelected': !lastInCollapsedThread() }">
|
|
||||||
<span lass="threadsCount" data-bind="visible: !lastInCollapsedThreadLoading(), text: threadsLenResult"></span>
|
|
||||||
<span lass="threadsCount" data-bind="visible: lastInCollapsedThreadLoading()">x</span>
|
|
||||||
</span>
|
|
||||||
<span class="replyFlag"><i class="icon-reply"></i> </span>
|
<span class="replyFlag"><i class="icon-reply"></i> </span>
|
||||||
<span class="forwardFlag"><i class="icon-forward"></i> </span>
|
<span class="forwardFlag"><i class="icon-forward"></i> </span>
|
||||||
<span class="sender" data-bind="text: senderEmailsString, attr: {'title': senderClearEmailsString}"></span>
|
<span class="sender" data-bind="text: senderEmailsString, attr: {'title': senderClearEmailsString}"></span>
|
||||||
|
<span class="thre" data-bind="visible: 1 < threadsLen()">
|
||||||
|
(<span data-bind="text: threadsLen"></span>)
|
||||||
|
</span>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="attachmentParent actionHandle dragHandle">
|
<div class="attachmentParent actionHandle dragHandle">
|
||||||
|
|
|
||||||
|
|
@ -182,14 +182,14 @@
|
||||||
<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: false" style="margin-right: 5px">
|
<div class="btn-group pull-right" data-bind="visible: viewThreadsControlVisibility" style="margin-right: 5px">
|
||||||
<a class="btn btn-thin" data-tooltip-placement="bottom">
|
<a class="btn btn-thin" data-tooltip-placement="bottom" data-bind="command: threadForwardCommand">
|
||||||
<i class="icon-left-middle"></i>
|
<i class="icon-left-middle"></i>
|
||||||
</a>
|
</a>
|
||||||
<a class="btn btn-thin" data-tooltip-placement="bottom">
|
<a class="btn btn-thin" data-tooltip-placement="bottom">
|
||||||
<b>1 / 4</b>
|
<b data-bind="html: viewThreadsControlDesc"></b>
|
||||||
</a>
|
</a>
|
||||||
<a class="btn btn-thin" data-tooltip-placement="bottom">
|
<a class="btn btn-thin" data-tooltip-placement="bottom" data-bind="command: threadBackCommand">
|
||||||
<i class="icon-right-middle"></i>
|
<i class="icon-right-middle"></i>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -202,12 +202,15 @@
|
||||||
<img class="fromPic" data-bind="visible: viewUserPicVisible, attr: {'src': viewUserPic() }">
|
<img class="fromPic" data-bind="visible: viewUserPicVisible, attr: {'src': viewUserPic() }">
|
||||||
<div style="overflow: hidden;">
|
<div style="overflow: hidden;">
|
||||||
<div class="subjectParent" data-bind="event: { 'dblclick': toggleFullScreen }">
|
<div class="subjectParent" data-bind="event: { 'dblclick': toggleFullScreen }">
|
||||||
|
<span class="flagParent">
|
||||||
|
<i class="icon-star-empty flagOff" data-bind="css: {'icon-star flagOn': viewIsFlagged, 'icon-star-empty flagOff': !viewIsFlagged()}"></i>
|
||||||
|
</span>
|
||||||
<b style="color:red;margin-right:5px" data-bind="visible: viewIsImportant">!</b>
|
<b style="color:red;margin-right:5px" data-bind="visible: viewIsImportant">!</b>
|
||||||
<span class="subject" data-bind="text: viewSubject, title: viewSubject"></span>
|
<span class="subject" data-bind="text: viewSubject, title: viewSubject"></span>
|
||||||
<span class="i18n emptySubjectText" data-i18n-text="MESSAGE/EMPTY_SUBJECT_TEXT"></span>
|
<span class="i18n emptySubjectText" data-i18n-text="MESSAGE/EMPTY_SUBJECT_TEXT"></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="senderParent">
|
<div class="senderParent">
|
||||||
<div class="g-ui-user-select-none" style="float: left; cursor: pointer;" data-bind="click: function() { showFullInfo(!showFullInfo()); }">
|
<div class="g-ui-user-select-none" style="float: left; cursor: pointer; margin-left: 1px;" data-bind="click: function() { showFullInfo(!showFullInfo()); }">
|
||||||
<i class="icon-right-dir" data-bind="css: showFullInfo() ? 'icon-down-dir' : 'icon-right-dir'"></i>
|
<i class="icon-right-dir" data-bind="css: showFullInfo() ? 'icon-down-dir' : 'icon-right-dir'"></i>
|
||||||
</div>
|
</div>
|
||||||
<div class="informationShort" data-bind="event: { 'dblclick': toggleFullScreen }">
|
<div class="informationShort" data-bind="event: { 'dblclick': toggleFullScreen }">
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue