snappymail/dev/View/User/MailBox/MessageList.js
SebaSalvaG e4ecda0e61 Don't reset the message list to page 1 and clear the search on message.show
The `mailbox.message.show` handler rewrote the hash to `mailBox(sFolder)` --
page 1, no search -- even when the user was already in that folder.

Because the hash of an open message carries the message id and the new one does
not, the two differ, the route fires again, the message is shown again, and the
handler runs again: a loop. Every iteration aborts whatever message list request
was pending, so browsing to page 2 or running a search silently bounces back to
page 1 of the INBOX with an empty search box.

Only navigate when we are not already in that folder. Clicking a new-mail
notification from another folder still takes you to the INBOX; if the message is
not in the current page, the else branch already opens it in the preview pane
without touching the list.

The same unconditional setHash a few lines below, for non-INBOX folders, gets
the same guard.
2026-08-23 22:38:40 +02:00

847 lines
23 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import ko from 'ko';
import { addObservablesTo, addComputablesTo } from 'External/ko';
import { UNUSED_OPTION_VALUE } from 'Common/Consts';
import { ScopeFolderList, ScopeMessageList, ScopeMessageView } from 'Common/Enums';
import { ComposeType, FolderType, MessageSetAction } from 'Common/EnumsUser';
import { doc,
leftPanelDisabled, toggleLeftPanel,
Settings, SettingsCapa,
addEventsListeners, stopEvent,
addShortcut, registerShortcut, formFieldFocused
} from 'Common/Globals';
import { arrayLength } from 'Common/Utils';
import { computedPaginatorHelper, showMessageComposer, populateMessageBody, downloadZip, moveAction } from 'Common/UtilsUser';
import { FileInfo, RFC822 } from 'Common/File';
import { isFullscreen, toggleFullscreen } from 'Common/Fullscreen';
import { mailBox } from 'Common/Links';
import { Selector } from 'Common/Selector';
import { i18n } from 'Common/Translator';
import { dropFilesInFolder } from 'Common/Folders';
import { getFolderFromCacheList } from 'Common/Cache';
import { AppUserStore } from 'Stores/User/App';
import { SettingsUserStore } from 'Stores/User/Settings';
import { FolderUserStore } from 'Stores/User/Folder';
import { LanguageStore } from 'Stores/Language';
import { MessageUserStore } from 'Stores/User/Message';
import { MessagelistUserStore } from 'Stores/User/Messagelist';
import { ThemeStore } from 'Stores/Theme';
import Remote from 'Remote/User/Fetch';
import { decorateKoCommands, showScreenPopup, arePopupsVisible } from 'Knoin/Knoin';
import { AbstractViewRight } from 'Knoin/AbstractViews';
import { FolderClearPopupView } from 'View/Popup/FolderClear';
import { AdvancedSearchPopupView } from 'View/Popup/AdvancedSearch';
import { ComposePopupView } from 'View/Popup/Compose';
import { MessageModel } from 'Model/Message';
import { LayoutSideView, ClientSideKeyNameMessageListSize } from 'Common/EnumsUser';
import { setLayoutResizer } from 'Common/UtilsUser';
const
canBeMovedHelper = () => MessagelistUserStore.hasCheckedOrSelected(),
/**
* @param {string} sFolderFullName
* @param {number} iSetAction
* @param {Array=} aMessages = null
* @returns {void}
*/
listAction = (...args) => MessagelistUserStore.setAction(...args),
moveMessagesToFolderType = (toFolderType, bDelete) => {
let messages = MessagelistUserStore.listCheckedOrSelectedUidsWithSubMails();
messages.size && rl.app.moveMessagesToFolderType(
toFolderType,
messages.folder,
messages,
bDelete
)
},
pad2 = v => 10 > v ? '0' + v : '' + v,
Ymd = dt => dt.getFullYear() + pad2(1 + dt.getMonth()) + pad2(dt.getDate()),
setMessage = msg => {
populateMessageBody(msg);
/* This will replace url hash, and then load message
* It's working properly yet
// let hash = msg.href;
let hash = mailBox(
msg.folder,
MessagelistUserStore.page(),
MessagelistUserStore.listSearch(),
MessagelistUserStore.threadUid(),
msg.uid
);
MessageUserStore.message() ? hasher.replaceHash(hash) : hasher.setHash(hash);
*/
};
let
sLastSearchValue = '';
export class MailMessageList extends AbstractViewRight {
constructor() {
super();
this.allowDangerousActions = SettingsCapa('DangerousActions');
this.messageList = MessagelistUserStore;
this.archiveAllowed = MessagelistUserStore.archiveAllowed;
this.canMarkAsSpam = MessagelistUserStore.canMarkAsSpam;
this.isSpamFolder = MessagelistUserStore.isSpamFolder;
this.composeInEdit = ComposePopupView.inEdit;
this.isMobile = ThemeStore.isMobile; // Obsolete
this.popupVisibility = arePopupsVisible;
this.useCheckboxesInList = SettingsUserStore.useCheckboxesInList;
this.userUsageProc = FolderUserStore.quotaPercentage;
this.hideDeleted = SettingsUserStore.hideDeleted;
addObservablesTo(this, {
focusSearch: false
});
// append drag and drop
this.dragOver = ko.observable(false).extend({ throttle: 1 });
this.dragOverEnter = ko.observable(false).extend({ throttle: 1 });
const attachmentsActions = Settings.app('attachmentsActions');
this.attachmentsActions = ko.observableArray(arrayLength(attachmentsActions) ? attachmentsActions : []);
addComputablesTo(this, {
sortSupported: () => FolderUserStore.hasCapability('SORT') && !MessagelistUserStore.threadUid(),
messageListSearchDesc: () => {
const value = MessagelistUserStore().search;
return value ? i18n('MESSAGE_LIST/SEARCH_RESULT_FOR', { SEARCH: value }) : ''
},
messageListPaginator: computedPaginatorHelper(MessagelistUserStore.page, MessagelistUserStore.pageCount),
checkAll: {
read: () => MessagelistUserStore.hasChecked(),
write: (value) => {
value = !!value;
MessagelistUserStore.forEach(message => message.checked(value));
}
},
inputSearch: {
read: MessagelistUserStore.mainSearch,
write: value => sLastSearchValue = value
},
isIncompleteChecked: () => {
const c = MessagelistUserStore.listChecked().length;
return c && MessagelistUserStore().length > c;
},
listGrouped: () => {
let uid = MessagelistUserStore.threadUid(),
sort = FolderUserStore.sortMode() || 'DATE';
return SettingsUserStore.listGrouped() && (sort.includes('DATE') || sort.includes('FROM')) && !uid;
},
timeFormat: () => (FolderUserStore.sortMode() || '').includes('FROM') ? 'AUTO' : 'LT',
groupedList: () => {
let list = [], current, sort = FolderUserStore.sortMode() || 'DATE';
if (sort.includes('FROM')) {
MessagelistUserStore.forEach(msg => {
let email = msg.from[0]?.email;
if (!current || email != current.id) {
current = {
id: email,
label: msg.from[0]?.toLine(),
search: 'from=' + email,
messages: []
};
list.push(current);
}
current.messages.push(msg);
});
} else if (sort.includes('DATE')) {
let today = Ymd(new Date()),
rtf = Intl.RelativeTimeFormat
? new Intl.RelativeTimeFormat(doc.documentElement.lang, { numeric: "auto" }) : 0;
MessagelistUserStore.forEach(msg => {
let dt = (new Date(msg.dateTimestamp() * 1000)),
date,
ymd = Ymd(dt);
if (!current || ymd != current.id) {
if (rtf && today == ymd) {
date = rtf.format(0, 'day');
} else if (rtf && today - 1 == ymd) {
date = rtf.format(-1, 'day');
// } else if (today - 7 < ymd) {
// date = dt.format({weekday: 'long'});
// date = dt.format({dateStyle: 'full'},0,LanguageStore.hourCycle());
} else {
// date = dt.format({dateStyle: 'medium'},0,LanguageStore.hourCycle());
date = dt.format({dateStyle: 'full'},0,LanguageStore.hourCycle());
}
current = {
id: ymd,
label: date,
search: 'on=' + dt.getFullYear() + '-' + pad2(1 + dt.getMonth()) + '-' + pad2(dt.getDate()),
messages: []
};
list.push(current);
}
current.messages.push(msg);
});
}
return list;
},
sortText: () => {
let mode = FolderUserStore.sortMode(),
has = w => mode.includes(w),
desc = '' === mode || has('REVERSE');
mode = mode.split(/\s+/);
if (has('FROM')) {
return '@' + (desc ? '⬆' : '⬇');
}
if (has('SUBJECT')) {
return '𝐒' + (desc ? '⬆' : '⬇');
}
if (has('SIZE')) {
return '✉' + (desc ? '⬇' : '⬆');
}
return (has('ARRIVAL') ? '📨' : '📅') + (desc ? '⬇' : '⬆');
},
downloadAsZipAllowed: () => this.attachmentsActions.includes('zip')
});
this.selector = new Selector(
MessagelistUserStore,
MessagelistUserStore.selectedMessage,
MessagelistUserStore.focusedMessage,
'.messageListItem',
'.messageListItem .messageCheckbox'
);
this.selector.on('ItemSelect', message => {
if (message) {
// setMessage(message.clone());
setMessage(message);
} else {
MessageUserStore.message(null);
}
});
this.selector.on('MiddleClick', message => populateMessageBody(message, true));
this.selector.on('ItemGetUid', message => (message ? message.folder + '/' + message.uid : ''));
this.selector.on('canSelect', () => MessagelistUserStore.canSelect());
this.selector.on('click', (event, currentMessage) => {
const el = event.target;
if (el.closest('.flagParent')) {
if (currentMessage) {
const checked = MessagelistUserStore.listCheckedOrSelected();
listAction(
currentMessage.folder,
currentMessage.isFlagged() ? MessageSetAction.UnsetFlag : MessageSetAction.SetFlag,
checked.find(message => message.uid == currentMessage.uid) ? checked : [currentMessage]
);
}
} else if (el.closest('.threads-len')) {
this.gotoThread(currentMessage);
} else {
return 1;
}
});
this.selector.on('UpOrDown', up => {
if (!MessagelistUserStore.hasChecked()) {
up = up ? -1 : 1;
const page = MessagelistUserStore.page() + up;
if (page > 0 && page <= MessagelistUserStore.pageCount()) {
if (SettingsUserStore.usePreviewPane() || MessageUserStore.message()) {
this.selector.iSelectNextHelper = up;
} else {
this.selector.iFocusedNextHelper = up;
}
this.selector.unselect();
this.gotoPage(page);
}
}
});
addEventListener('mailbox.message-list.selector.go-down',
e => this.selector.newSelectPosition('ArrowDown', false, e.detail)
);
addEventListener('mailbox.message-list.selector.go-up',
e => this.selector.newSelectPosition('ArrowUp', false, e.detail)
);
addEventListener('mailbox.message.show', e => {
const sFolder = e.detail.folder, iUid = e.detail.uid;
const message = MessagelistUserStore.find(
item => sFolder === item?.folder && iUid == item?.uid
);
if ('INBOX' === sFolder && 'INBOX' !== FolderUserStore.currentFolderFullName()) {
hasher.setHash(mailBox(sFolder));
}
if (message) {
this.selector.selectMessageItem(message);
} else {
if ('INBOX' !== sFolder && sFolder !== FolderUserStore.currentFolderFullName()) {
hasher.setHash(mailBox(sFolder));
}
if (sFolder && iUid) {
let message = new MessageModel;
message.folder = sFolder;
message.uid = iUid;
setMessage(message);
} else {
MessageUserStore.message(null);
}
}
});
MessagelistUserStore.endHash.subscribe((() =>
this.selector.scrollToFocused()
).throttle(50));
decorateKoCommands(this, {
downloadAttachCommand: canBeMovedHelper,
downloadZipCommand: canBeMovedHelper,
forwardCommand: canBeMovedHelper,
deleteWithoutMoveCommand: canBeMovedHelper,
deleteCommand: () => MessagelistUserStore.hasCheckedOrSelectedAndUndeleted(),
undeleteCommand: () => MessagelistUserStore.hasCheckedOrSelectedAndDeleted(),
archiveCommand: canBeMovedHelper,
spamCommand: canBeMovedHelper,
notSpamCommand: canBeMovedHelper,
moveCommand: canBeMovedHelper,
copyCommand: canBeMovedHelper
});
}
changeSort(self, event) {
FolderUserStore.sortMode(event.target.closest('li').dataset.sort);
this.reload();
}
clearListIsVisible() {
return (
!this.messageListSearchDesc()
&& !MessagelistUserStore.error()
&& !MessagelistUserStore.endThreadUid()
&& MessagelistUserStore().length
&& (MessagelistUserStore.isSpamFolder() || MessagelistUserStore.isTrashFolder())
&& SettingsCapa('DangerousActions')
);
}
clear() {
SettingsCapa('DangerousActions')
&& showScreenPopup(FolderClearPopupView, [FolderUserStore.currentFolder()]);
}
reload() {
MessagelistUserStore.isLoading()
|| MessagelistUserStore.reload(false, true);
}
forwardCommand() {
showMessageComposer([
ComposeType.ForwardAsAttachment,
MessagelistUserStore.listCheckedOrSelected()
]);
}
/**
* Download selected messages
*/
downloadZipCommand() {
let hashes = []/*, uids = []*/;
// MessagelistUserStore.forEach(message => message.checked() && uids.push(message.uid));
MessagelistUserStore.forEach(message => message.checked() && hashes.push(message.requestHash));
downloadZip(null, hashes, null, null, MessagelistUserStore().folder);
}
/**
* Download attachments of selected messages
*/
downloadAttachCommand() {
let hashes = [];
MessagelistUserStore.forEach(message => {
if (message.checked()) {
message.attachments.forEach(attachment => {
if (!attachment.isLinked() && attachment.download) {
hashes.push(attachment.download);
}
});
}
});
downloadZip(null, hashes);
}
deleteWithoutMoveCommand() {
SettingsCapa('DangerousActions')
&& moveMessagesToFolderType(FolderType.Trash, true);
}
// User setting hideDeleted || immediatelyMoveToTrash ??
deleteCommand() {
/**
* When FolderUserStore.trashFolder is set to "Do not use",
* flag as \Deleted for removal by later EXPUNGE
*/
if (UNUSED_OPTION_VALUE === FolderUserStore.trashFolder()) {
listAction(
FolderUserStore.currentFolderFullName(),
MessageSetAction.SetDeleted,
MessagelistUserStore.listCheckedOrSelected()
);
} else {
moveMessagesToFolderType(FolderType.Trash);
}
}
// User setting !hideDeleted && !immediatelyMoveToTrash ??
undeleteCommand() {
listAction(
FolderUserStore.currentFolderFullName(),
MessageSetAction.UnsetDeleted,
MessagelistUserStore.listCheckedOrSelected()
);
}
archiveCommand() {
moveMessagesToFolderType(FolderType.Archive);
}
spamCommand() {
moveMessagesToFolderType(FolderType.Junk);
}
notSpamCommand() {
moveMessagesToFolderType(FolderType.Inbox);
}
moveOrCopy(vm, event, mode) {
if (canBeMovedHelper()) {
if (vm && event?.preventDefault) {
stopEvent(event);
}
let i = moveAction();
AppUserStore.focusedState(i ? ScopeMessageList : ScopeFolderList);
moveAction(i ? 0 : mode);
}
}
moveCommand(vm, event) {
this.moveOrCopy(vm, event, 1);
}
copyCommand(vm, event) {
this.moveOrCopy(vm, event, 2);
}
composeClick() {
showMessageComposer();
}
cancelSearch() {
MessagelistUserStore.mainSearch('');
this.focusSearch(false);
}
cancelThreadUid() {
// history.go(-1) better?
hasher.setHash(
mailBox(
FolderUserStore.currentFolderFullNameHash(),
MessagelistUserStore.pageBeforeThread(),
MessagelistUserStore.listSearch()
)
);
}
listSetSeen() {
listAction(
FolderUserStore.currentFolderFullName(),
MessageSetAction.SetSeen,
MessagelistUserStore.listCheckedOrSelected()
);
}
listSetAllSeen() {
let sFolderFullName = FolderUserStore.currentFolderFullName(),
iThreadUid = MessagelistUserStore.endThreadUid();
if (sFolderFullName) {
let cnt = 0;
const uids = [];
let folder = getFolderFromCacheList(sFolderFullName);
if (folder) {
MessagelistUserStore.forEach(message => {
if (message.isUnseen()) {
++cnt;
}
message.flags.push('\\seen');
// message.flags.valueHasMutated();
iThreadUid && uids.push(message.uid);
});
if (iThreadUid) {
folder.unreadEmails(Math.max(0, folder.unreadEmails() - cnt));
} else {
folder.unreadEmails(0);
}
Remote.request('MessageSetSeenToAll', null, {
folder: sFolderFullName,
setAction: 1,
threadUids: uids.join(',')
});
}
}
}
listUnsetSeen() {
listAction(
FolderUserStore.currentFolderFullName(),
MessageSetAction.UnsetSeen,
MessagelistUserStore.listCheckedOrSelected()
);
}
listSetFlags() {
listAction(
FolderUserStore.currentFolderFullName(),
MessageSetAction.SetFlag,
MessagelistUserStore.listCheckedOrSelected()
);
}
listUnsetFlags() {
listAction(
FolderUserStore.currentFolderFullName(),
MessageSetAction.UnsetFlag,
MessagelistUserStore.listCheckedOrSelected()
);
}
seenMessagesFast(seen) {
const checked = MessagelistUserStore.listCheckedOrSelected();
if (checked.length) {
listAction(
checked[0].folder,
seen ? MessageSetAction.SetSeen : MessageSetAction.UnsetSeen,
checked
);
}
}
gotoPage(page) {
page && hasher.setHash(
mailBox(
FolderUserStore.currentFolderFullNameHash(),
page,
MessagelistUserStore.listSearch(),
MessagelistUserStore.threadUid()
)
);
}
gotoThread(message) {
if (message?.threadsLen()) {
MessagelistUserStore.pageBeforeThread(MessagelistUserStore.page());
hasher.setHash(
mailBox(FolderUserStore.currentFolderFullNameHash(), 1, MessagelistUserStore.listSearch(), message.uid)
);
}
}
listEmptyMessage() {
if (!this.dragOver()
&& !MessagelistUserStore().length
&& !MessagelistUserStore.isLoading()
&& !MessagelistUserStore.error()) {
return i18n('MESSAGE_LIST/EMPTY_' + (MessagelistUserStore.listSearch() ? 'SEARCH_' : '') + 'LIST');
}
return '';
}
onBuild(dom) {
const b_content = dom.querySelector('.b-content'),
eqs = (ev, s) => ev.target.closestWithin(s, dom);
setTimeout(() => {
// initMailboxLayoutResizer
const top = dom.querySelector('.messageList'),
fToggle = () => {
let layout = SettingsUserStore.usePreviewPane();
setLayoutResizer(top, ClientSideKeyNameMessageListSize,
layout ? (LayoutSideView === layout ? 'Width' : 'Height') : 0
);
};
if (top) {
fToggle();
addEventListener('rl-layout', fToggle);
}
}, 1);
this.selector.init(b_content, ScopeMessageList);
addEventsListeners(dom, {
click: event => {
if (eqs(event, '.toggleLeft')) {
toggleLeftPanel();
} else {
ThemeStore.isMobile() && leftPanelDisabled(true);
if (eqs(event, '.messageList') && ScopeMessageView === AppUserStore.focusedState()) {
AppUserStore.focusedState(ScopeMessageList);
}
let el = eqs(event, '.e-paginator a');
el && this.gotoPage(ko.dataFor(el)?.value);
eqs(event, '.checkboxCheckAll') && this.checkAll(!this.checkAll());
}
},
dblclick: event => {
let msg = ko.dataFor(eqs(event, '.messageListItem'));
if (msg) {
msg.threadsLen() ? this.gotoThread(msg) : toggleFullscreen();
}
}
});
// initUploaderForAppend
if (Settings.app('allowAppendMessage')) {
const dropZone = dom.querySelector('.listDragOver'),
validFiles = oEvent => {
for (const item of oEvent.dataTransfer.items) {
if ('file' === item.kind && RFC822 === item.type) {
return true;
}
}
};
addEventsListeners(dropZone, {
dragover: oEvent => {
if (validFiles(oEvent)) {
oEvent.dataTransfer.dropEffect = 'copy';
oEvent.preventDefault();
}
},
});
addEventsListeners(b_content, {
dragenter: oEvent => {
if (validFiles(oEvent)) {
if (b_content.contains(oEvent.target)) {
this.dragOver(true);
}
if (oEvent.target == dropZone) {
oEvent.dataTransfer.dropEffect = 'copy';
this.dragOverEnter(true);
}
}
},
dragleave: oEvent => {
if (oEvent.target == dropZone) {
this.dragOverEnter(false);
}
let related = oEvent.relatedTarget;
if (!related || !b_content.contains(related)) {
this.dragOver(false);
}
},
drop: oEvent => {
oEvent.preventDefault();
if (oEvent.target == dropZone && validFiles(oEvent)) {
MessagelistUserStore.loading(true);
dropFilesInFolder(FolderUserStore.currentFolderFullName(), oEvent.dataTransfer.files);
}
this.dragOverEnter(false);
this.dragOver(false);
}
});
}
// initShortcuts
addShortcut('enter,open', '', ScopeMessageList, () => {
if (formFieldFocused()) {
MessagelistUserStore.mainSearch(sLastSearchValue);
return false;
}
if (MessageUserStore.message() && MessagelistUserStore.canSelect()) {
isFullscreen() || toggleFullscreen();
return false;
}
});
// archive (zip)
registerShortcut('z', '', [ScopeMessageList, ScopeMessageView], () => {
this.archiveCommand();
return false;
});
// delete
registerShortcut('delete', 'shift', ScopeMessageList, () => {
MessagelistUserStore.listCheckedOrSelected().length && this.deleteWithoutMoveCommand();
return false;
});
// registerShortcut('3', 'shift', ScopeMessageList, () => {
registerShortcut('delete', '', ScopeMessageList, () => {
MessagelistUserStore.listCheckedOrSelected().length && this.deleteCommand();
return false;
});
// check mail
addShortcut('r', 'meta', [ScopeFolderList, ScopeMessageList, ScopeMessageView], () => {
this.reload();
return false;
});
// check all
registerShortcut('a', 'meta', ScopeMessageList, () => {
this.checkAll(!(this.checkAll() && !this.isIncompleteChecked()));
return false;
});
// write/compose (open compose popup)
registerShortcut('w,c,new', '', [ScopeMessageList, ScopeMessageView], () => {
showMessageComposer();
return false;
});
// important - star/flag messages
registerShortcut('i', '', [ScopeMessageList, ScopeMessageView], () => {
const checked = MessagelistUserStore.listCheckedOrSelected();
if (checked.length) {
listAction(
checked[0].folder,
checked.every(message => message.isFlagged()) ? MessageSetAction.UnsetFlag : MessageSetAction.SetFlag,
checked
);
}
return false;
});
registerShortcut('t', '', [ScopeMessageList], () => {
let message = MessagelistUserStore.selectedMessage() || MessagelistUserStore.focusedMessage();
if (0 < message?.threadsLen()) {
this.gotoThread(message);
}
return false;
});
// move
registerShortcut('insert', '', ScopeMessageList, () => {
this.moveCommand();
return false;
});
// read
registerShortcut('q', '', [ScopeMessageList, ScopeMessageView], () => {
this.seenMessagesFast(true);
return false;
});
// unread
registerShortcut('u', '', [ScopeMessageList, ScopeMessageView], () => {
this.seenMessagesFast(false);
return false;
});
registerShortcut('f,mailforward', 'shift', [ScopeMessageList, ScopeMessageView], () => {
this.forwardCommand();
return false;
});
if (SettingsCapa('Search')) {
// search input focus
addShortcut('/', '', [ScopeMessageList, ScopeMessageView], () => {
this.focusSearch(true);
return false;
});
}
// cancel search
addShortcut('escape', '', ScopeMessageList, () => {
if (this.messageListSearchDesc()) {
this.cancelSearch();
return false;
} else if (MessagelistUserStore.endThreadUid()) {
this.cancelThreadUid();
return false;
}
});
// change focused state
addShortcut('tab', 'shift', ScopeMessageList, () => {
AppUserStore.focusedState(ScopeFolderList);
return false;
});
addShortcut('arrowleft', '', ScopeMessageList, () => {
AppUserStore.focusedState(ScopeFolderList);
return false;
});
addShortcut('tab,arrowright', '', ScopeMessageList, () => {
if (MessageUserStore.message()) {
AppUserStore.focusedState(ScopeMessageView);
return false;
}
});
addShortcut('arrowleft', 'meta', ScopeMessageView, ()=>false);
addShortcut('arrowright', 'meta', ScopeMessageView, ()=>false);
addShortcut('f', 'meta', ScopeMessageList, this.advancedSearchClick);
}
advancedSearchClick() {
showScreenPopup(AdvancedSearchPopupView, [MessagelistUserStore.mainSearch()]);
}
groupSearch(group) {
group.search && MessagelistUserStore.mainSearch(group.search);
}
groupCheck(group) {
group.messages.forEach(message => message.checked(!message.checked()));
}
quotaTooltip() {
return i18n('MESSAGE_LIST/QUOTA_SIZE', {
SIZE: FileInfo.friendlySize(FolderUserStore.quotaUsage()),
PROC: FolderUserStore.quotaPercentage(),
LIMIT: FileInfo.friendlySize(FolderUserStore.quotaLimit())
}).replace(/<[^>]+>/g, '');
}
}