mirror of
https://github.com/the-djmaze/snappymail.git
synced 2025-09-10 07:04:53 +08:00
New thread list logic (step 2)
This commit is contained in:
parent
b656b6365b
commit
03d26bc4c6
18 changed files with 139 additions and 517 deletions
|
@ -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);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -272,7 +272,7 @@
|
|||
|
||||
if ('' !== sFolder)
|
||||
{
|
||||
sResult += encodeURI(sFolder) + (0 < iThreadUid ? '|' + iThreadUid : '');
|
||||
sResult += encodeURI(sFolder) + (0 < iThreadUid ? '~' + iThreadUid : '');
|
||||
}
|
||||
|
||||
if (1 < iPage)
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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}]
|
||||
];
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -142,7 +142,7 @@
|
|||
border-color: transparent;
|
||||
border-top-color: #999;
|
||||
|
||||
animation: rotation .8s infinite linear;
|
||||
animation: rotation .8s infinite ease-in-out;
|
||||
}
|
||||
|
||||
&.big {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -42,12 +42,12 @@
|
|||
<tr><td class="i18n" data-i18n="SHORTCUTS_HELP/LABEL_CHECK_ALL"></td><td>Ctrl + A, Cmd + A</td></tr>
|
||||
<tr><td class="i18n" data-i18n="SHORTCUTS_HELP/LABEL_ARCHIVE"></td><td>Z</td></tr>
|
||||
<tr><td class="i18n" data-i18n="SHORTCUTS_HELP/LABEL_DELETE"></td><td>Delete, Shift + Delete, #</td></tr>
|
||||
<tr><td class="i18n" data-i18n="SHORTCUTS_HELP/LABEL_OPEN_THREAD"></td><td>T</td></tr>
|
||||
<tr><td class="i18n" data-i18n="SHORTCUTS_HELP/LABEL_MOVE"></td><td>M</td></tr>
|
||||
<tr><td class="i18n" data-i18n="SHORTCUTS_HELP/LABEL_READ"></td><td>Q</td></tr>
|
||||
<tr><td class="i18n" data-i18n="SHORTCUTS_HELP/LABEL_UNREAD"></td><td>U</td></tr>
|
||||
<tr><td class="i18n" data-i18n="SHORTCUTS_HELP/LABEL_IMPORTANT"></td><td>I</td></tr>
|
||||
<tr><td class="i18n" data-i18n="SHORTCUTS_HELP/LABEL_SEARCH"></td><td>/</td></tr>
|
||||
<tr><td class="i18n" data-i18n="SHORTCUTS_HELP/LABEL_CANCEL_SEARCH"></td><td>Esc</td></tr>
|
||||
<tr><td class="i18n" data-i18n="SHORTCUTS_HELP/LABEL_FULLSCREEN_ENTER"></td><td>Enter</td></tr>
|
||||
<tr><td class="i18n" data-i18n="SHORTCUTS_HELP/LABEL_VIEW_MESSAGE_ENTER"></td><td>Enter</td></tr>
|
||||
<tr><td class="i18n" data-i18n="SHORTCUTS_HELP/LABEL_SWITCH_TO_MESSAGE"></td><td>→, Tab</td></tr>
|
||||
|
@ -60,14 +60,12 @@
|
|||
|
||||
<table class="table table-striped table-bordered">
|
||||
<tbody>
|
||||
<tr><td class="i18n" data-i18n="SHORTCUTS_HELP/LABEL_FULLSCREEN_TOGGLE">Toggle fullscreen mode</td><td>Enter</td></tr>
|
||||
<tr><td class="i18n" data-i18n="SHORTCUTS_HELP/LABEL_BLOCKQUOTES_TOGGLE">Toggle message blockquotes</td><td>B</td></tr>
|
||||
<tr><td class="i18n" data-i18n="SHORTCUTS_HELP/LABEL_THREAD_NEXT">Next message in thread</td><td>Ctrl + ←, Cmd + ←</td></tr>
|
||||
<tr><td class="i18n" data-i18n="SHORTCUTS_HELP/LABEL_THREAD_PREV">Previous message in thread</td><td>Ctrl + →, Cmd + →</td></tr>
|
||||
<tr><td class="i18n" data-i18n="SHORTCUTS_HELP/LABEL_PRINT">Print</td><td>Ctrl + P, Cmd + P</td></tr>
|
||||
<tr><td class="i18n" data-i18n="SHORTCUTS_HELP/LABEL_EXIT_FULLSCREEN">Exit fullscreen mode</td><td>Esc</td></tr>
|
||||
<tr><td class="i18n" data-i18n="SHORTCUTS_HELP/LABEL_CLOSE_MESSAGE">Close message (No preview pane layout)</td><td>Esc</td></tr>
|
||||
<tr><td class="i18n" data-i18n="SHORTCUTS_HELP/LABEL_SWITCH_TO_LIST">Switch focus back to message list</td><td>Tab, Shift + Tab, Esc</td></tr>
|
||||
<tr><td class="i18n" data-i18n="SHORTCUTS_HELP/LABEL_FULLSCREEN_TOGGLE"></td><td>Enter</td></tr>
|
||||
<tr><td class="i18n" data-i18n="SHORTCUTS_HELP/LABEL_BLOCKQUOTES_TOGGLE"></td><td>B</td></tr>
|
||||
<tr><td class="i18n" data-i18n="SHORTCUTS_HELP/LABEL_PRINT"></td><td>Ctrl + P, Cmd + P</td></tr>
|
||||
<tr><td class="i18n" data-i18n="SHORTCUTS_HELP/LABEL_EXIT_FULLSCREEN"></td><td>Esc</td></tr>
|
||||
<tr><td class="i18n" data-i18n="SHORTCUTS_HELP/LABEL_CLOSE_MESSAGE"></td><td>Esc</td></tr>
|
||||
<tr><td class="i18n" data-i18n="SHORTCUTS_HELP/LABEL_SWITCH_TO_LIST"></td><td>Tab, Shift + Tab, Esc</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
|
|
@ -137,12 +137,14 @@
|
|||
<div class="b-content" data-bind="nano: true, initDom: dragOverBodyArea">
|
||||
<div class="content g-scrollbox">
|
||||
<div class="content-wrapper">
|
||||
<div class="listThreadUidDesc" data-bind="visible: '' !== messageListEndThreadUid(), click: cancelThreadUid">
|
||||
<i class="icon-left" data-bind="click: cancelThreadUid"></i>
|
||||
|
||||
<span class="i18n" data-i18n="MESSAGE_LIST/BACK_TO_MESSAGE_LIST"></span>
|
||||
</div>
|
||||
<div class="listSearchDesc" data-bind="visible: '' !== messageListSearchDesc()">
|
||||
<a class="close-custom" data-bind="click: cancelSearch">×</a>
|
||||
<!-- <a class="btn btn-small pull-right searchCancelButton" data-bind="click: cancelSearch">
|
||||
<i class="icon-remove"></i>
|
||||
</a>-->
|
||||
<span data-bind="text: messageListSearchDesc"></span>:
|
||||
<span data-bind="text: messageListSearchDesc"></span>
|
||||
</div>
|
||||
<div class="listDragOver" data-bind="css: {'viewAppendArea': dragOver() && '' === messageListError() && !popupVisibility(), 'dragOverEnter': dragOverEnter }, initDom: dragOverArea">
|
||||
<i class="icon-down e-icon"></i>
|
||||
|
|
|
@ -18,15 +18,20 @@
|
|||
<div class="dateParent actionHandle dragHandle">
|
||||
<span class="date" data-moment-format="SHORT" data-moment-format-title="FULL" data-bind="moment: dateTimeStampInUTC"></span>
|
||||
</div>
|
||||
<div class="threadsParent" data-bind="visible: 1 < threadsLen()">
|
||||
<span class="threads-len">
|
||||
<span class="threads-len-data">
|
||||
<span data-bind="text: threadsLen"></span>
|
||||
<i class="icon-right-mini"></i>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="checkedParent">
|
||||
<i class="checkboxMessage" data-bind="css: checked() ? 'checkboxMessage icon-checkbox-checked' : 'checkboxMessage icon-checkbox-unchecked'"></i>
|
||||
</div>
|
||||
<div class="senderParent actionHandle dragHandle">
|
||||
<span class="replyFlag"><i class="icon-reply"></i> </span>
|
||||
<span class="forwardFlag"><i class="icon-forward"></i> </span>
|
||||
<span class="threads-len" data-bind="visible: 1 < threadsLen()">
|
||||
<span class="threads-len-data" data-bind="text: threadsLen"></span>
|
||||
</span>
|
||||
<span class="sender" data-bind="text: senderEmailsString, attr: {'title': senderClearEmailsString}"></span>
|
||||
|
||||
</div>
|
||||
|
|
|
@ -7,6 +7,14 @@
|
|||
<div class="dateParent actionHandle dragHandle">
|
||||
<span class="date" data-moment-format="SHORT" data-moment-format-title="FULL" data-bind="moment: dateTimeStampInUTC"></span>
|
||||
</div>
|
||||
<div class="threadsParent" data-bind="visible: 1 < threadsLen()">
|
||||
<span class="threads-len">
|
||||
<span class="threads-len-data">
|
||||
<span data-bind="text: threadsLen"></span>
|
||||
<i class="icon-right-mini"></i>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="checkedParent">
|
||||
<i class="checkboxMessage" data-bind="css: checked() ? 'checkboxMessage icon-checkbox-checked' : 'checkboxMessage icon-checkbox-unchecked'"></i>
|
||||
</div>
|
||||
|
@ -24,9 +32,6 @@
|
|||
<div class="senderParent actionHandle dragHandle">
|
||||
<span class="replyFlag"><i class="icon-reply"></i> </span>
|
||||
<span class="forwardFlag"><i class="icon-forward"></i> </span>
|
||||
<span class="threads-len" data-bind="visible: 1 < threadsLen()">
|
||||
<span class="threads-len-data" data-bind="text: threadsLen"></span>
|
||||
</span>
|
||||
<span class="sender" data-bind="text: senderEmailsString, attr: {'title': senderClearEmailsString}"></span>
|
||||
|
||||
</div>
|
||||
|
|
|
@ -188,67 +188,6 @@
|
|||
</a>
|
||||
</div>
|
||||
|
||||
<div class="btn-group thread-controls pull-right g-ui-user-select-none" style="margin-right: 5px"
|
||||
data-bind="visible: viewThreadsControlVisibility">
|
||||
|
||||
<a class="btn last btn-thin pull-right" data-tooltip-join="bottom"
|
||||
data-bind="command: threadBackCommand, tooltip: 'MESSAGE/BUTTON_THREAD_PREV'">
|
||||
<i class="icon-right-middle"></i>
|
||||
</a>
|
||||
<div class="btn-group pull-right" data-bind="registrateBootstrapDropdown: true, openDropdownTrigger: threadsDropdownTrigger">
|
||||
<a class="btn btn-thin btn-dark-disabled-border dropdown-toggle" id="thread-list-view-dropdown-id" data-toggle="dropdown"
|
||||
href="#" tabindex="-1" data-tooltip-join="bottom"
|
||||
style="margin-left: -1px; margin-right: -1px;"
|
||||
data-bind="command: threadListCommand, tooltip: 'MESSAGE/BUTTON_THREAD_LIST'"
|
||||
>
|
||||
<i class="icon-list"
|
||||
data-bind="css: {'icon-list': !messageListOfThreadsLoading(), 'icon-spinner animated': messageListOfThreadsLoading()}"></i>
|
||||
</a>
|
||||
<ul class="dropdown-menu pull-right g-ui-menu thread-list"
|
||||
role="menu" aria-labelledby="thread-list-view-dropdown-id"
|
||||
style="min-width: 400px; max-width: 400px; width: 400px; padding: 0"
|
||||
data-bind="css: {'hide-more': !viewThreadMessages.showMore() }"
|
||||
>
|
||||
|
||||
<div data-bind="visible: '' !== viewThreadMessages.error()" style="color: red; text-align: center; padding: 10px">
|
||||
<spam data-bind="text: viewThreadMessages.error"></spam>
|
||||
</div>
|
||||
<div data-bind="visible: messageListOfThreadsLoading" style="text-align: center; padding: 10px">
|
||||
<i class="icon-spinner animated" />
|
||||
</div>
|
||||
<div data-bind="foreach: viewThreadMessages, visible: !messageListOfThreadsLoading()">
|
||||
<li class="e-item thread-list-message real-msg" role="presentation" data-bind="css: {'selected': selected, 'more-that': $parent.viewThreadMessages.limit < $index() }">
|
||||
<a class="e-link menuitem" href="#" tabindex="-1" onclick="return false;">
|
||||
<span class="flagParent pull-right" style="margin-left: 5px; margin-right: 0px;">
|
||||
<i class="icon-star-empty flagOff" data-bind="css: {'icon-star flagOn': flagged, 'icon-star-empty flagOff': !flagged()}"></i>
|
||||
</span>
|
||||
<span class="thread-date pull-right" data-moment-format="SHORT" data-bind="moment: timestamp"></span>
|
||||
<div style="text-overflow: ellipsis; overflow: hidden;">
|
||||
<span class="thread-from" data-bind="text: fromAsString"></span>
|
||||
|
||||
</div>
|
||||
<div style="text-overflow: ellipsis; overflow: hidden;">
|
||||
<span class="thread-subject" data-bind="text: subject"></span>
|
||||
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
</div>
|
||||
<div data-bind="visible: !viewThreadMessages.showMore() && !messageListOfThreadsLoading()">
|
||||
<li class="e-item thread-list-message" role="presentation">
|
||||
<a class="e-link menuitem more-threads" href="#" tabindex="-1"
|
||||
onclick="return false"
|
||||
data-i18n="MESSAGE/BUTTON_THREAD_MORE"></a>
|
||||
</li>
|
||||
</div>
|
||||
</ul>
|
||||
</div>
|
||||
<a class="btn first btn-thin pull-right" data-tooltip-join="bottom"
|
||||
data-bind="command: threadForwardCommand, tooltip: 'MESSAGE/BUTTON_THREAD_NEXT'">
|
||||
<i class="icon-left-middle"></i>
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</nobr>
|
||||
</div>
|
||||
|
||||
|
@ -261,9 +200,6 @@
|
|||
<span class="flagParent">
|
||||
<i class="icon-star-empty flagOff" data-bind="css: {'icon-star flagOn': viewIsFlagged, 'icon-star-empty flagOff': !viewIsFlagged()}"></i>
|
||||
</span>
|
||||
<span class="thread-counter" data-bind="visible: viewThreadsControlVisibility"
|
||||
style="font-weight: normal; margin-right: 5px">(<span
|
||||
data-bind="text: viewThreadsControlDesc"></span>)</span>
|
||||
<b style="color: red; margin-right: 5px" data-bind="visible: viewIsImportant">!</b>
|
||||
<span class="subject" data-bind="text: viewSubject, title: viewSubject"></span>
|
||||
<span class="i18n emptySubjectText" data-i18n="MESSAGE/EMPTY_SUBJECT_TEXT"></span>
|
||||
|
|
Loading…
Add table
Reference in a new issue