From 03d26bc4c638fea94c0e22f271f0d9c6efcc8169 Mon Sep 17 00:00:00 2001 From: RainLoop Team Date: Tue, 21 Apr 2015 02:39:14 +0400 Subject: [PATCH] New thread list logic (step 2) --- dev/App/User.js | 13 -- dev/Common/Links.js | 2 +- dev/Common/Selector.js | 9 +- dev/Promises/User/Ajax.js | 34 --- dev/Remote/User/Ajax.js | 42 ---- dev/Screen/User/MailBox.js | 12 +- dev/Stores/User/Message.js | 50 +--- dev/Styles/MessageList.less | 24 +- dev/Styles/_FontasticToBoot.less | 2 +- dev/View/User/MailBox/MessageList.js | 49 ++++ dev/View/User/MailBox/MessageView.js | 221 +----------------- .../app/libraries/MailSo/Mail/MailClient.php | 11 +- .../0.0.0/app/libraries/RainLoop/Actions.php | 75 +----- .../Common/PopupsKeyboardShortcutsHelp.html | 16 +- .../templates/Views/User/MailMessageList.html | 10 +- .../Views/User/MailMessageListItem.html | 11 +- .../MailMessageListItemNoPreviewPane.html | 11 +- .../templates/Views/User/MailMessageView.html | 64 ----- 18 files changed, 139 insertions(+), 517 deletions(-) diff --git a/dev/App/User.js b/dev/App/User.js index bb622b736..55efe8b3f 100644 --- a/dev/App/User.js +++ b/dev/App/User.js @@ -153,20 +153,7 @@ Cache.initMessageFlagsFromCache(oMessage); }); - _.each(MessageStore.messageThreadList(), function (oMessage) { - Cache.initMessageFlagsFromCache(oMessage); - }); - Cache.initMessageFlagsFromCache(MessageStore.message()); - - this.reloadFlagsCurrentMessageThreadListFromCache(); - }; - - AppUser.prototype.reloadFlagsCurrentMessageThreadListFromCache = function () - { - _.each(MessageStore.messageThreadList(), function (oMessage) { - Cache.initMessageFlagsFromCache(oMessage); - }); }; /** diff --git a/dev/Common/Links.js b/dev/Common/Links.js index ac0e57c7c..1383694e8 100644 --- a/dev/Common/Links.js +++ b/dev/Common/Links.js @@ -272,7 +272,7 @@ if ('' !== sFolder) { - sResult += encodeURI(sFolder) + (0 < iThreadUid ? '|' + iThreadUid : ''); + sResult += encodeURI(sFolder) + (0 < iThreadUid ? '~' + iThreadUid : ''); } if (1 < iPage) diff --git a/dev/Common/Selector.js b/dev/Common/Selector.js index 0918e42b1..be7ed462c 100644 --- a/dev/Common/Selector.js +++ b/dev/Common/Selector.js @@ -633,13 +633,20 @@ var iOffset = 20, + aList = this.list(), oFocused = $(this.sItemFocusedSelector, this.oContentScrollable), oPos = oFocused.position(), iVisibleHeight = this.oContentVisible.height(), iFocusedHeight = oFocused.outerHeight() ; - if (oPos && (oPos.top < 0 || oPos.top + iFocusedHeight > iVisibleHeight)) + if (aList && aList[0] && aList[0].focused()) + { + this.oContentScrollable.scrollTop(0); + + return true; + } + else if (oPos && (oPos.top < 0 || oPos.top + iFocusedHeight > iVisibleHeight)) { if (oPos.top < 0) { diff --git a/dev/Promises/User/Ajax.js b/dev/Promises/User/Ajax.js index 6dec2b76f..e37362cfa 100644 --- a/dev/Promises/User/Ajax.js +++ b/dev/Promises/User/Ajax.js @@ -29,44 +29,10 @@ function UserAjaxUserPromises() { AbstractAjaxPromises.call(this); - - this.messageListSimpleHash = ''; - this.messageListSimpleCache = null; } _.extend(UserAjaxUserPromises.prototype, AbstractAjaxPromises.prototype); - UserAjaxUserPromises.prototype.messageListSimple = function (sFolder, aUids, fTrigger) - { - var self = this, sHash = sFolder + '~' + aUids.join('/'); - if (sHash === this.messageListSimpleHash && this.messageListSimpleCache) - { - return this.fastResolve(this.messageListSimpleCache); - } - - return this.abort('MessageListSimple') - .postRequest('MessageListSimple', fTrigger, { - 'Folder': sFolder, - 'Uids': aUids - }).then(function (oData) { - - self.messageListSimpleHash = sHash; - self.messageListSimpleCache = _.compact(_.map(oData.Result, function (aItem) { - return MessageSimpleModel.newInstanceFromJson(aItem); - })); - - return self.messageListSimpleCache; - - }, function (iError) { - - self.messageListSimpleHash = ''; - self.messageListSimpleCache = null; - - return self.fastReject(iError); - }) - ; - }; - UserAjaxUserPromises.prototype.foldersReload = function (fTrigger) { return this.abort('Folders') diff --git a/dev/Remote/User/Ajax.js b/dev/Remote/User/Ajax.js index e7c8ee969..9aa3408f0 100644 --- a/dev/Remote/User/Ajax.js +++ b/dev/Remote/User/Ajax.js @@ -313,19 +313,6 @@ }); }; - /** - * @param {?Function} fCallback - * @param {string} sFolderFullNameRaw - * @param {Array} aUids - */ - RemoteUserAjax.prototype.messageListSimple = function (fCallback, sFolderFullNameRaw, aUids) - { - return this.defaultRequest(fCallback, 'MessageListSimple', { - 'Folder': Utils.pString(sFolderFullNameRaw), - 'Uids': aUids - }, Consts.Defaults.DefaultAjaxTimeout, '', ['MessageListSimple']); - }; - /** * @param {?Function} fCallback * @param {string} sFolderFullNameRaw @@ -420,35 +407,6 @@ return false; }; - /** - * @param {?Function} fCallback - * @param {string} sFolderFullNameRaw - * @param {number} iUid - * @return {boolean} - */ - RemoteUserAjax.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 {Array} aExternals diff --git a/dev/Screen/User/MailBox.js b/dev/Screen/User/MailBox.js index c69dce10a..a08625507 100644 --- a/dev/Screen/User/MailBox.js +++ b/dev/Screen/User/MailBox.js @@ -75,9 +75,9 @@ MailBoxUserScreen.prototype.onRoute = function (sFolderHash, iPage, sSearch) { var - sThreadUid = sFolderHash.replace(/^(.+)\|([\d]+)$/, '$2'), + sThreadUid = sFolderHash.replace(/^(.+)~([\d]+)$/, '$2'), oFolder = Cache.getFolderFromCacheList(Cache.getFolderFullNameRaw( - sFolderHash.replace(/\|([\d]+)$/, ''))) + sFolderHash.replace(/~([\d]+)$/, ''))) ; if (oFolder) @@ -88,7 +88,7 @@ } FolderStore.currentFolder(oFolder); - + MessageStore.messageListPage(iPage); MessageStore.messageListSearch(sSearch); MessageStore.messageListThreadUid(sThreadUid); @@ -171,9 +171,9 @@ ; return [ - [/^([a-zA-Z0-9]+)\/p([1-9][0-9]*)\/(.+)\/?$/, {'normalize_': fNormS}], - [/^([a-zA-Z0-9]+)\/p([1-9][0-9]*)$/, {'normalize_': fNormS}], - [/^([a-zA-Z0-9]+)\/(.+)\/?$/, {'normalize_': fNormD}], + [/^([a-zA-Z0-9~]+)\/p([1-9][0-9]*)\/(.+)\/?$/, {'normalize_': fNormS}], + [/^([a-zA-Z0-9~]+)\/p([1-9][0-9]*)$/, {'normalize_': fNormS}], + [/^([a-zA-Z0-9~]+)\/(.+)\/?$/, {'normalize_': fNormD}], [/^([^\/]*)$/, {'normalize_': fNormS}] ]; }; diff --git a/dev/Stores/User/Message.js b/dev/Stores/User/Message.js index becf5fea4..2632a5f9a 100644 --- a/dev/Stores/User/Message.js +++ b/dev/Stores/User/Message.js @@ -43,10 +43,12 @@ this.messageListSearch = ko.observable(''); this.messageListThreadUid = ko.observable(''); this.messageListPage = ko.observable(1); + this.messageListPageBeforeThread = ko.observable(1); this.messageListError = ko.observable(''); this.messageListEndFolder = ko.observable(''); this.messageListEndSearch = ko.observable(''); + this.messageListEndThreadUid = ko.observable(''); this.messageListEndPage = ko.observable(1); this.messageListLoading = ko.observable(false); @@ -64,17 +66,12 @@ this.message.viewTrigger = ko.observable(false); - this.messageThreadList = ko.observableArray([]); - - this.messageLastThreadUidsData = ko.observable(null); - this.messageError = ko.observable(''); this.messageCurrentLoading = ko.observable(false); - this.messageThreadLoading = ko.observable(false); this.messageLoading = ko.computed(function () { - return !!(this.messageCurrentLoading() || this.messageThreadLoading()); + return this.messageCurrentLoading(); }, this); this.messageLoadingThrottle = ko.observable(false).extend({'throttle': 50}); @@ -94,8 +91,12 @@ MessageUserStore.prototype.computers = function () { + var self = this; + this.messageListEndHash = ko.computed(function () { - return this.messageListEndFolder() + '|' + this.messageListEndSearch() + '|' + this.messageListEndPage(); + return this.messageListEndFolder() + '|' + this.messageListEndSearch() + + '|' + this.messageListEndThreadUid() + + '|' + this.messageListEndPage(); }, this); this.messageListPageCount = ko.computed(function () { @@ -108,7 +109,8 @@ 'read': this.messageListSearch, 'write': function (sValue) { kn.setHash(Links.mailBox( - FolderStore.currentFolderFullNameHash(), 1, Utils.trim(sValue.toString()) + FolderStore.currentFolderFullNameHash(), 1, + Utils.trim(sValue.toString()), self.messageListThreadUid() )); }, 'owner': this @@ -666,14 +668,6 @@ } }; - MessageUserStore.prototype.selectThreadMessage = function (sFolder, sUid) - { - if (Remote.message(this.onMessageResponse, sFolder, sUid)) - { - this.messageThreadLoading(true); - } - }; - MessageUserStore.prototype.populateMessageBody = function (oMessage) { if (oMessage) @@ -695,7 +689,6 @@ this.hideMessageBodies(); this.messageCurrentLoading(false); - this.messageThreadLoading(false); if (Enums.StorageResultType.Success === sResult && oData && oData.Result) { @@ -817,7 +810,8 @@ this.messageListThreadUid(Utils.isNormal(oData.Result.ThreadUid) ? Utils.pString(oData.Result.ThreadUid) : ''); this.messageListEndFolder(Utils.isNormal(oData.Result.Folder) ? oData.Result.Folder : ''); - this.messageListEndSearch(Utils.isNormal(oData.Result.Search) ? oData.Result.Search : ''); + this.messageListEndSearch(this.messageListSearch()); + this.messageListEndThreadUid(this.messageListThreadUid()); this.messageListEndPage(this.messageListPage()); this.messageListDisableAutoSelect(true); @@ -827,26 +821,6 @@ 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())) { require('App/User').folderInformation(oFolder.fullNameRaw, aList); diff --git a/dev/Styles/MessageList.less b/dev/Styles/MessageList.less index 4c7dba60a..eba936ca0 100644 --- a/dev/Styles/MessageList.less +++ b/dev/Styles/MessageList.less @@ -178,6 +178,15 @@ html.rl-no-preview-pane { border-bottom: 1px solid #eee; } + .listThreadUidDesc { + font-size: 16px; + padding: 7px 20px 5px 20px; + border-bottom: 1px solid #eee; + background-color: #FCF8E3; + cursor: pointer; + text-align: center; + } + .delimiter { display: block; height: 1px; @@ -313,6 +322,12 @@ html.rl-no-preview-pane { &.e-single-line .dateParent { } + .threadsParent { + display: inline-block; + float: right; + position: relative; + } + .attachmentParent { display: inline-block; float: right; @@ -398,8 +413,13 @@ html.rl-no-preview-pane { background-color: #999; color: #fff; border-radius: 6px; - padding: 1px 6px 1px 5px; - margin-right: 5px; + padding: 1px 2px 1px 5px; + margin-right: 2px; + + [class^="icon-"], + [class*=" icon-"] { + font-size: 14px; + } } } diff --git a/dev/Styles/_FontasticToBoot.less b/dev/Styles/_FontasticToBoot.less index 9e61f787a..70b25dae9 100644 --- a/dev/Styles/_FontasticToBoot.less +++ b/dev/Styles/_FontasticToBoot.less @@ -142,7 +142,7 @@ border-color: transparent; border-top-color: #999; - animation: rotation .8s infinite linear; + animation: rotation .8s infinite ease-in-out; } &.big { diff --git a/dev/View/User/MailBox/MessageList.js b/dev/View/User/MailBox/MessageList.js index 7eab8a1fc..373e5dc27 100644 --- a/dev/View/User/MailBox/MessageList.js +++ b/dev/View/User/MailBox/MessageList.js @@ -70,6 +70,7 @@ this.mainMessageListSearch = MessageStore.mainMessageListSearch; this.messageListEndFolder = MessageStore.messageListEndFolder; + this.messageListEndThreadUid = MessageStore.messageListEndThreadUid; this.messageListChecked = MessageStore.messageListChecked; this.messageListCheckedOrSelected = MessageStore.messageListCheckedOrSelected; @@ -389,6 +390,15 @@ this.inputMessageListSearchFocus(false); }; + MessageListMailBoxUserView.prototype.cancelThreadUid = function () + { + kn.setHash(Links.mailBox( + FolderStore.currentFolderFullNameHash(), + MessageStore.messageListPageBeforeThread(), + MessageStore.messageListSearch() + )); + }; + /** * @param {string} sToFolderFullNameRaw * @param {boolean} bCopy @@ -618,6 +628,21 @@ } }; + MessageListMailBoxUserView.prototype.gotoThread = function (oMessage) + { + if (oMessage) + { + MessageStore.messageListPageBeforeThread(MessageStore.messageListPage()); + + kn.setHash(Links.mailBox( + FolderStore.currentFolderFullNameHash(), + 1, + MessageStore.messageListSearch(), + oMessage.uid + )); + } + }; + MessageListMailBoxUserView.prototype.onBuild = function (oDom) { var self = this; @@ -643,6 +668,9 @@ .on('click', '.messageList .messageListItem .flagParent', function () { self.flagMessages(ko.dataFor(this)); }) + .on('click', '.messageList .messageListItem .threads-len', function () { + self.gotoThread(ko.dataFor(this)); + }) ; this.initUploaderForAppend(); @@ -725,6 +753,22 @@ return false; }); + key('t', [Enums.KeyState.MessageList], function () { + + var oMessage = self.selectorMessageSelected(); + if (!oMessage) + { + oMessage = self.selectorMessageFocused(); + } + + if (oMessage && 0 < oMessage.threadsLen()) + { + self.gotoThread(oMessage); + } + + return false; + }); + // move key('m', Enums.KeyState.MessageList, function () { self.moveDropdownTrigger(true); @@ -761,6 +805,11 @@ self.cancelSearch(); return false; } + else if ('' !== self.messageListEndThreadUid()) + { + self.cancelThreadUid(); + return false; + } }); // change focused state diff --git a/dev/View/User/MailBox/MessageView.js b/dev/View/User/MailBox/MessageView.js index fdba28c18..c6399e990 100644 --- a/dev/View/User/MailBox/MessageView.js +++ b/dev/View/User/MailBox/MessageView.js @@ -229,164 +229,6 @@ this.viewIsImportant = ko.observable(false); this.viewIsFlagged = ko.observable(false); -// THREADS - this.viewThreads = ko.observableArray([]); - this.viewThreads.trigger = ko.observable(false); - - this.viewThreadMessages = MessageStore.messageThreadList; - - this.viewThreadMessages.error = ko.observable(''); - this.viewThreadMessages.showMore = ko.observable(false); - this.viewThreadMessages.limit = 6; - - this.viewThreadMessages.subscribe(function (aList) { - - var iSelectedIndex = -1; - - this.viewThreadMessages.error(''); - if (aList && 0 < aList.length) - { - _.each(aList, function (oM, iIndex) { - if (oM && oM.selected()) - { - iSelectedIndex = iIndex; - } - }); - - this.viewThreadMessages.showMore(this.viewThreadMessages.limit >= aList.length); - - if (-1 < iSelectedIndex && !this.viewThreadMessages.showMore() && - this.viewThreadMessages.limit < iSelectedIndex) - { - this.viewThreadMessages.showMore(true); - } - - this.selectSelectedThreadMessage(); - require('App/User').reloadFlagsCurrentMessageListAndMessageFromCache(); - } - - }, this); - - 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); - - this.threadsDropdownTrigger = ko.observable(false); - - this.threadListCommand = Utils.createCommand(this, function () { - - var - self = this, - sFolder = this.viewFolder, - sUid = this.viewUid, - aUids = this.viewThreads(), - aStatus = this.viewThreads.status() - ; - - if (aStatus && aStatus[0]) - { - self.viewThreadMessages([]); - - Promises.messageListSimple(sFolder, aUids, this.messageListOfThreadsLoading).then(function (aList) { - - _.each(aList, function (oItem) { - if (oItem && oItem.uid) - { - oItem.selected(sUid === oItem.uid); - } - }); - - self.viewThreadMessages(aList); - - }).fail(function (iErrorCode) { - self.viewThreadMessages([]); - self.viewThreadMessages.error(Translator.getNotification( - iErrorCode, '', Enums.Notification.CantGetMessageList)); - }).done(); - } - - }, function () { - return !this.messageLoadingThrottle() && - !this.messageListOfThreadsLoading(); - }); - // PGP this.viewPgpPassword = ko.observable(''); this.viewPgpSignedVerifyStatus = ko.computed(function () { @@ -472,9 +314,6 @@ this.viewIsImportant(oMessage.isImportant()); this.viewIsFlagged(oMessage.flagged()); - this.viewThreads(oMessage.threads()); - this.viewThreads.trigger(!this.viewThreads.trigger()); - sLastEmail = oMessage.fromAsSingleEmail(); Cache.getUserPic(sLastEmail, function (sPic, sEmail) { if (sPic !== self.viewUserPic() && sLastEmail === sEmail) @@ -495,8 +334,6 @@ this.viewUid = ''; this.viewHash = ''; - this.viewThreads([]); - this.scrollMessageToTop(); } @@ -555,15 +392,6 @@ kn.extendAsViewModel(['View/User/MailBox/MessageView', 'View/App/MailBox/MessageView', 'MailBoxMessageViewViewModel'], MessageViewMailBoxUserView); _.extend(MessageViewMailBoxUserView.prototype, AbstractView.prototype); - MessageViewMailBoxUserView.prototype.openThreadMessage = function (sUid) - { - var oMessage = this.message(); - if (oMessage && sUid) - { - MessageStore.selectThreadMessage(oMessage.folderFullNameRaw, sUid); - } - }; - MessageViewMailBoxUserView.prototype.isPgpActionVisible = function () { return Enums.SignedVerifyStatus.Success !== this.viewPgpSignedVerifyStatus(); @@ -791,32 +619,6 @@ } } }) - .on('click', '.thread-list .more-threads', function (e) { - - var oLast = null; - if (!e || 0 === e.clientX) // probably enter - { - // It's a bad bad hack :( - oLast = $('.thread-list .e-item.thread-list-message.real-msg.more-that:first a.e-link', oDom); - } - - self.viewThreadMessages.showMore(true); - self.threadsDropdownTrigger(true); - - if (oLast && oLast[0]) - { - oLast.focus(); - } - - return false; - }) - .on('click', '.thread-list .thread-list-message', function () { - var oMessage = ko.dataFor(this); - if (oMessage && oMessage.folder && oMessage.uid) - { - self.openThreadMessage(oMessage.uid); - } - }) .on('click', '.attachmentsPlace .attachmentItem .attachmentNameParent', function () { var @@ -970,35 +772,16 @@ } }); - key('t', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { - if (MessageStore.message() && self.viewThreadsControlVisibility()) - { - self.threadsDropdownTrigger(true); - self.threadListCommand(); - return false; - } - }); - - key('ctrl+up, command+up', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { + key('ctrl+up, command+up, ctrl+left, command+left', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { self.goUpCommand(); return false; }); - key('ctrl+down, command+down', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { + key('ctrl+down, command+down, ctrl+right, command+right', [Enums.KeyState.MessageList, Enums.KeyState.MessageView], function () { self.goDownCommand(); 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 key('ctrl+p, command+p', Enums.KeyState.MessageView, function () { if (self.message()) diff --git a/rainloop/v/0.0.0/app/libraries/MailSo/Mail/MailClient.php b/rainloop/v/0.0.0/app/libraries/MailSo/Mail/MailClient.php index e2450810d..14faa9903 100644 --- a/rainloop/v/0.0.0/app/libraries/MailSo/Mail/MailClient.php +++ b/rainloop/v/0.0.0/app/libraries/MailSo/Mail/MailClient.php @@ -1916,6 +1916,7 @@ class MailClient * @param string $sSearch * @param string $sFolderName * @param string $sFolderHash + * @param bool $bUseSortIfSupported = false * * @return array * @@ -1923,7 +1924,7 @@ class MailClient * @throws \MailSo\Net\Exceptions\Exception * @throws \MailSo\Imap\Exceptions\Exception */ - public function GetUids($oCacher, $sSearch, $sFolderName, $sFolderHash) + public function GetUids($oCacher, $sSearch, $sFolderName, $sFolderHash, $bUseSortIfSupported = false) { $aResultUids = false; $bUidsFromCacher = false; @@ -1932,7 +1933,7 @@ class MailClient $sSerializedHash = ''; $sSerializedLog = ''; - $bUseSortIfSupported = !!$this->oImapClient->IsSupported('SORT'); + $bUseSortIfSupported = $bUseSortIfSupported ? !!$this->oImapClient->IsSupported('SORT') : false; if (0 < \strlen($sSearch)) { @@ -2078,7 +2079,11 @@ class MailClient if (0 < $iMessageRealCount) { - $mAllSortedUids = $this->GetUids($oCacher, '', $oMessageCollection->FolderName, $oMessageCollection->FolderHash); + $mAllSortedUids = $this->GetUids($oCacher, '', $oMessageCollection->FolderName, $oMessageCollection->FolderHash, $bUseSortIfSupported); + + $bUseSortIfSupported = $bUseSortIfSupported ? $this->oImapClient->IsSupported('SORT') : false; + +// $bUseThreadSortIfSupported = $bUseThreadSortIfSupported ? $mAllThreads = $bUseThreadSortIfSupported ? $this->MessageListThreadsMap( $oMessageCollection->FolderName, $oMessageCollection->FolderHash, $mAllSortedUids, $oCacher) : null; diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Actions.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Actions.php index 37aa0afc0..8183a243b 100644 --- a/rainloop/v/0.0.0/app/libraries/RainLoop/Actions.php +++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Actions.php @@ -5455,45 +5455,6 @@ class Actions 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 * @@ -5501,7 +5462,7 @@ class Actions */ public function DoMessageList() { -// \sleep(1); + \sleep(1); // throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::CantGetMessageList); $sFolder = ''; @@ -5581,40 +5542,6 @@ class Actions return $this->DefaultResponse(__FUNCTION__, $oMessageList); } - /** - * @return array - * - * @throws \MailSo\Base\Exceptions\Exception - */ - public function DoMessageListSimple() - { -// \sleep(2); -// throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::CantGetMessageList); - - $sFolder = $this->GetActionParam('Folder', ''); - $aUids = $this->GetActionParam('Uids', null); - - if (0 === \strlen($sFolder) || !\is_array($aUids)) - { - throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::InvalidInputArgument); - } - - $this->initMailClientConnection(); - - $aMessageList = array(); - - try - { - $aMessageList = $this->MailClient()->MessageListSimple($sFolder, $aUids); - } - catch (\Exception $oException) - { - throw new \RainLoop\Exceptions\ClientException(\RainLoop\Notifications::CantGetMessageList, $oException); - } - - return $this->DefaultResponse(__FUNCTION__, $aMessageList); - } - /** * @param \RainLoop\Model\Account $oAccount * @param bool $bWithDraftInfo = true diff --git a/rainloop/v/0.0.0/app/templates/Views/Common/PopupsKeyboardShortcutsHelp.html b/rainloop/v/0.0.0/app/templates/Views/Common/PopupsKeyboardShortcutsHelp.html index 93b5391da..0ded19103 100644 --- a/rainloop/v/0.0.0/app/templates/Views/Common/PopupsKeyboardShortcutsHelp.html +++ b/rainloop/v/0.0.0/app/templates/Views/Common/PopupsKeyboardShortcutsHelp.html @@ -42,12 +42,12 @@ Ctrl + A, Cmd + A Z Delete, Shift + Delete, # + T M Q U I / - Esc Enter Enter →, Tab @@ -60,14 +60,12 @@ - - - - - - - - + + + + + +
Toggle fullscreen modeEnter
Toggle message blockquotesB
Next message in threadCtrl + ←, Cmd + ←
Previous message in threadCtrl + →, Cmd + →
PrintCtrl + P, Cmd + P
Exit fullscreen modeEsc
Close message (No preview pane layout)Esc
Switch focus back to message listTab, Shift + Tab, Esc
Enter
B
Ctrl + P, Cmd + P
Esc
Esc
Tab, Shift + Tab, Esc
diff --git a/rainloop/v/0.0.0/app/templates/Views/User/MailMessageList.html b/rainloop/v/0.0.0/app/templates/Views/User/MailMessageList.html index dbc806cfe..6c96d5104 100644 --- a/rainloop/v/0.0.0/app/templates/Views/User/MailMessageList.html +++ b/rainloop/v/0.0.0/app/templates/Views/User/MailMessageList.html @@ -137,12 +137,14 @@
+
+ +    + +
× - - : +
diff --git a/rainloop/v/0.0.0/app/templates/Views/User/MailMessageListItem.html b/rainloop/v/0.0.0/app/templates/Views/User/MailMessageListItem.html index c269f835c..a83231b3a 100644 --- a/rainloop/v/0.0.0/app/templates/Views/User/MailMessageListItem.html +++ b/rainloop/v/0.0.0/app/templates/Views/User/MailMessageListItem.html @@ -18,15 +18,20 @@
+
+ + + + + + +
    - - -  
diff --git a/rainloop/v/0.0.0/app/templates/Views/User/MailMessageListItemNoPreviewPane.html b/rainloop/v/0.0.0/app/templates/Views/User/MailMessageListItemNoPreviewPane.html index e8a81aa9c..e16ec903b 100644 --- a/rainloop/v/0.0.0/app/templates/Views/User/MailMessageListItemNoPreviewPane.html +++ b/rainloop/v/0.0.0/app/templates/Views/User/MailMessageListItemNoPreviewPane.html @@ -7,6 +7,14 @@
+
+ + + + + + +
@@ -24,9 +32,6 @@
    - - -  
diff --git a/rainloop/v/0.0.0/app/templates/Views/User/MailMessageView.html b/rainloop/v/0.0.0/app/templates/Views/User/MailMessageView.html index ee19b8d48..a4310c4ac 100644 --- a/rainloop/v/0.0.0/app/templates/Views/User/MailMessageView.html +++ b/rainloop/v/0.0.0/app/templates/Views/User/MailMessageView.html @@ -188,67 +188,6 @@
-
- - - - -
- - - - -
- - - - -
@@ -261,9 +200,6 @@ - () !