mirror of
https://github.com/the-djmaze/snappymail.git
synced 2024-11-11 01:23:43 +08:00
661cd2aaf9
Split list code from MessageUserStore into MessagelistUserStore Move functions out of AppUser
435 lines
12 KiB
JavaScript
435 lines
12 KiB
JavaScript
import { koComputable } from 'External/ko';
|
|
|
|
import { MessageSetAction } from 'Common/EnumsUser';
|
|
import { $htmlCL } from 'Common/Globals';
|
|
import { arrayLength, pInt, pString } from 'Common/Utils';
|
|
import { addObservablesTo, addComputablesTo } from 'External/ko';
|
|
|
|
import {
|
|
getFolderInboxName,
|
|
addNewMessageCache,
|
|
setFolderUidNext,
|
|
getFolderFromCacheList,
|
|
setFolderHash,
|
|
MessageFlagsCache,
|
|
clearNewMessageCache
|
|
} from 'Common/Cache';
|
|
|
|
import { mailBox } from 'Common/Links';
|
|
import { i18n, getNotification } from 'Common/Translator';
|
|
|
|
import { EmailCollectionModel } from 'Model/EmailCollection';
|
|
import { MessageCollectionModel } from 'Model/MessageCollection';
|
|
|
|
import { AccountUserStore } from 'Stores/User/Account';
|
|
import { FolderUserStore } from 'Stores/User/Folder';
|
|
import { MessageUserStore } from 'Stores/User/Message';
|
|
import { NotificationUserStore } from 'Stores/User/Notification';
|
|
import { SettingsUserStore } from 'Stores/User/Settings';
|
|
|
|
//import Remote from 'Remote/User/Fetch'; // Circular dependency
|
|
|
|
const
|
|
isChecked = item => item.checked();
|
|
|
|
export const MessagelistUserStore = ko.observableArray().extend({ debounce: 0 });
|
|
|
|
addObservablesTo(MessagelistUserStore, {
|
|
count: 0,
|
|
listSearch: '',
|
|
threadUid: 0,
|
|
page: 1,
|
|
pageBeforeThread: 1,
|
|
error: '',
|
|
|
|
endHash: '',
|
|
endThreadUid: 0,
|
|
|
|
loading: false,
|
|
// Happens when message(s) removed from list
|
|
isIncomplete: false,
|
|
|
|
selectedMessage: null,
|
|
focusedMessage: null
|
|
});
|
|
|
|
MessagelistUserStore.disableAutoSelect = ko.observable(false).extend({ falseTimeout: 500 });
|
|
|
|
// Computed Observables
|
|
|
|
addComputablesTo(MessagelistUserStore, {
|
|
isLoading: () => {
|
|
const value = MessagelistUserStore.loading() | MessagelistUserStore.isIncomplete();
|
|
$htmlCL.toggle('list-loading', value);
|
|
return value;
|
|
},
|
|
|
|
pageCount: () => Math.max(1, Math.ceil(MessagelistUserStore.count() / SettingsUserStore.messagesPerPage())),
|
|
|
|
mainSearch: {
|
|
read: MessagelistUserStore.listSearch,
|
|
write: value => rl.route.setHash(
|
|
mailBox(FolderUserStore.currentFolderFullNameHash(), 1,
|
|
value.toString().trim(), MessagelistUserStore.threadUid())
|
|
)
|
|
},
|
|
|
|
listCheckedOrSelected: () => {
|
|
const
|
|
selectedMessage = MessagelistUserStore.selectedMessage(),
|
|
focusedMessage = MessagelistUserStore.focusedMessage(),
|
|
checked = MessagelistUserStore.filter(item => isChecked(item) || item === selectedMessage);
|
|
return checked.length ? checked : (focusedMessage ? [focusedMessage] : []);
|
|
},
|
|
|
|
listCheckedOrSelectedUidsWithSubMails: () => {
|
|
let result = [];
|
|
MessagelistUserStore.listCheckedOrSelected().forEach(message => {
|
|
result.push(message.uid);
|
|
if (1 < message.threadsLen()) {
|
|
result = result.concat(message.threads()).unique();
|
|
}
|
|
});
|
|
return result;
|
|
}
|
|
});
|
|
|
|
MessagelistUserStore.listChecked = koComputable(
|
|
() => MessagelistUserStore.filter(isChecked)).extend({ rateLimit: 0 }
|
|
);
|
|
|
|
MessagelistUserStore.hasCheckedMessages = koComputable(
|
|
() => !!MessagelistUserStore.find(isChecked)
|
|
).extend({ rateLimit: 0 });
|
|
|
|
MessagelistUserStore.hasCheckedOrSelected = koComputable(() =>
|
|
!!(MessagelistUserStore.selectedMessage()
|
|
|| MessagelistUserStore.focusedMessage()
|
|
|| MessagelistUserStore.find(item => item.checked()))
|
|
).extend({ rateLimit: 50 });
|
|
|
|
MessagelistUserStore.initUidNextAndNewMessages = (folder, uidNext, newMessages) => {
|
|
if (getFolderInboxName() === folder && uidNext) {
|
|
if (arrayLength(newMessages)) {
|
|
newMessages.forEach(item => addNewMessageCache(folder, item.Uid));
|
|
|
|
NotificationUserStore.playSoundNotification();
|
|
|
|
const len = newMessages.length;
|
|
if (3 < len) {
|
|
NotificationUserStore.displayDesktopNotification(
|
|
AccountUserStore.email(),
|
|
i18n('MESSAGE_LIST/NEW_MESSAGE_NOTIFICATION', {
|
|
COUNT: len
|
|
}),
|
|
{ Url: mailBox(newMessages[0].Folder) }
|
|
);
|
|
} else {
|
|
newMessages.forEach(item => {
|
|
NotificationUserStore.displayDesktopNotification(
|
|
EmailCollectionModel.reviveFromJson(item.From).toString(),
|
|
item.Subject,
|
|
{ Folder: item.Folder, Uid: item.Uid }
|
|
);
|
|
});
|
|
}
|
|
}
|
|
|
|
setFolderUidNext(folder, uidNext);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param {boolean=} bDropPagePosition = false
|
|
* @param {boolean=} bDropCurrenFolderCache = false
|
|
*/
|
|
MessagelistUserStore.reload = (bDropPagePosition = false, bDropCurrenFolderCache = false) => {
|
|
let iOffset = (MessagelistUserStore.page() - 1) * SettingsUserStore.messagesPerPage();
|
|
|
|
if (bDropCurrenFolderCache) {
|
|
setFolderHash(FolderUserStore.currentFolderFullName(), '');
|
|
}
|
|
|
|
if (bDropPagePosition) {
|
|
MessagelistUserStore.page(1);
|
|
MessagelistUserStore.pageBeforeThread(1);
|
|
iOffset = 0;
|
|
|
|
rl.route.setHash(
|
|
mailBox(
|
|
FolderUserStore.currentFolderFullNameHash(),
|
|
MessagelistUserStore.page(),
|
|
MessagelistUserStore.listSearch(),
|
|
MessagelistUserStore.threadUid()
|
|
),
|
|
true,
|
|
true
|
|
);
|
|
}
|
|
|
|
MessagelistUserStore.loading(true);
|
|
MessagelistUserStore.error('');
|
|
rl.app.Remote.messageList(
|
|
(iError, oData, bCached) => {
|
|
if (iError) {
|
|
if (Notification.RequestAborted !== iError) {
|
|
MessagelistUserStore([]);
|
|
MessagelistUserStore.error(getNotification(iError));
|
|
}
|
|
} else {
|
|
const collection = MessageCollectionModel.reviveFromJson(oData.Result, bCached);
|
|
if (collection) {
|
|
let unreadCountChange = false;
|
|
|
|
const
|
|
folder = getFolderFromCacheList(collection.Folder);
|
|
|
|
if (folder && !bCached) {
|
|
folder.expires = Date.now();
|
|
|
|
setFolderHash(collection.Folder, collection.FolderHash);
|
|
|
|
if (null != collection.MessageCount) {
|
|
folder.messageCountAll(collection.MessageCount);
|
|
}
|
|
|
|
if (null != collection.MessageUnseenCount) {
|
|
if (pInt(folder.messageCountUnread()) !== pInt(collection.MessageUnseenCount)) {
|
|
unreadCountChange = true;
|
|
MessageFlagsCache.clearFolder(folder.fullName);
|
|
}
|
|
|
|
folder.messageCountUnread(collection.MessageUnseenCount);
|
|
}
|
|
|
|
MessagelistUserStore.initUidNextAndNewMessages(folder.fullName, collection.UidNext, collection.NewMessages);
|
|
}
|
|
|
|
MessagelistUserStore.count(collection.MessageResultCount);
|
|
MessagelistUserStore.listSearch(pString(collection.Search));
|
|
MessagelistUserStore.page(Math.ceil(collection.Offset / SettingsUserStore.messagesPerPage() + 1));
|
|
MessagelistUserStore.threadUid(collection.ThreadUid);
|
|
|
|
MessagelistUserStore.endHash(
|
|
collection.Folder +
|
|
'|' + collection.Search +
|
|
'|' + MessagelistUserStore.threadUid() +
|
|
'|' + MessagelistUserStore.page()
|
|
);
|
|
MessagelistUserStore.endThreadUid(collection.ThreadUid);
|
|
const message = MessageUserStore.message();
|
|
if (message && collection.Folder !== message.folder) {
|
|
MessageUserStore.message(null);
|
|
}
|
|
|
|
MessagelistUserStore.disableAutoSelect(true);
|
|
|
|
MessagelistUserStore(collection);
|
|
MessagelistUserStore.isIncomplete(false);
|
|
|
|
clearNewMessageCache();
|
|
|
|
if (folder && (bCached || unreadCountChange || SettingsUserStore.useThreads())) {
|
|
rl.app.folderInformation(folder.fullName, collection);
|
|
}
|
|
} else {
|
|
MessagelistUserStore.count(0);
|
|
MessagelistUserStore([]);
|
|
MessagelistUserStore.error(getNotification(Notification.CantGetMessageList));
|
|
}
|
|
}
|
|
MessagelistUserStore.loading(false);
|
|
},
|
|
{
|
|
Folder: FolderUserStore.currentFolderFullName(),
|
|
Offset: iOffset,
|
|
Limit: SettingsUserStore.messagesPerPage(),
|
|
Search: MessagelistUserStore.listSearch(),
|
|
ThreadUid: MessagelistUserStore.threadUid()
|
|
}
|
|
);
|
|
};
|
|
|
|
/**
|
|
* @param {string} sFolderFullName
|
|
* @param {number} iSetAction
|
|
* @param {Array=} messages = null
|
|
*/
|
|
MessagelistUserStore.setAction = (sFolderFullName, iSetAction, messages) => {
|
|
messages = messages || MessagelistUserStore.listChecked();
|
|
|
|
let folder = null,
|
|
alreadyUnread = 0,
|
|
rootUids = messages.map(oMessage => oMessage && oMessage.uid ? oMessage.uid : null)
|
|
.validUnique(),
|
|
length = rootUids.length;
|
|
|
|
if (sFolderFullName && length) {
|
|
switch (iSetAction) {
|
|
case MessageSetAction.SetSeen:
|
|
length = 0;
|
|
// fallthrough is intentionally
|
|
case MessageSetAction.UnsetSeen:
|
|
rootUids.forEach(sSubUid =>
|
|
alreadyUnread += MessageFlagsCache.storeBySetAction(sFolderFullName, sSubUid, iSetAction)
|
|
);
|
|
|
|
folder = getFolderFromCacheList(sFolderFullName);
|
|
if (folder) {
|
|
folder.messageCountUnread(folder.messageCountUnread() - alreadyUnread + length);
|
|
}
|
|
|
|
rl.app.Remote.request('MessageSetSeen', null, {
|
|
Folder: sFolderFullName,
|
|
Uids: rootUids.join(','),
|
|
SetAction: iSetAction == MessageSetAction.SetSeen ? 1 : 0
|
|
});
|
|
break;
|
|
|
|
case MessageSetAction.SetFlag:
|
|
case MessageSetAction.UnsetFlag:
|
|
rootUids.forEach(sSubUid =>
|
|
MessageFlagsCache.storeBySetAction(sFolderFullName, sSubUid, iSetAction)
|
|
);
|
|
rl.app.Remote.request('MessageSetFlagged', null, {
|
|
Folder: sFolderFullName,
|
|
Uids: rootUids.join(','),
|
|
SetAction: iSetAction == MessageSetAction.SetFlag ? 1 : 0
|
|
});
|
|
break;
|
|
// no default
|
|
}
|
|
|
|
MessagelistUserStore.reloadFlagsAndCachedMessage();
|
|
}
|
|
};
|
|
|
|
/**
|
|
* @param {string} fromFolderFullName
|
|
* @param {Array} uidForRemove
|
|
* @param {string=} toFolderFullName = ''
|
|
* @param {boolean=} copy = false
|
|
*/
|
|
MessagelistUserStore.removeMessagesFromList = (
|
|
fromFolderFullName, uidForRemove, toFolderFullName = '', copy = false
|
|
) => {
|
|
uidForRemove = uidForRemove.map(mValue => pInt(mValue));
|
|
|
|
let unseenCount = 0,
|
|
messageList = MessagelistUserStore,
|
|
currentMessage = MessageUserStore.message();
|
|
|
|
const trashFolder = FolderUserStore.trashFolder(),
|
|
spamFolder = FolderUserStore.spamFolder(),
|
|
fromFolder = getFolderFromCacheList(fromFolderFullName),
|
|
toFolder = toFolderFullName ? getFolderFromCacheList(toFolderFullName) : null,
|
|
messages =
|
|
FolderUserStore.currentFolderFullName() === fromFolderFullName
|
|
? messageList.filter(item => item && uidForRemove.includes(pInt(item.uid)))
|
|
: [];
|
|
|
|
messages.forEach(item => {
|
|
if (item && item.isUnseen()) {
|
|
++unseenCount;
|
|
}
|
|
});
|
|
|
|
if (fromFolder && !copy) {
|
|
fromFolder.messageCountAll(
|
|
0 <= fromFolder.messageCountAll() - uidForRemove.length ? fromFolder.messageCountAll() - uidForRemove.length : 0
|
|
);
|
|
|
|
if (0 < unseenCount) {
|
|
fromFolder.messageCountUnread(
|
|
0 <= fromFolder.messageCountUnread() - unseenCount ? fromFolder.messageCountUnread() - unseenCount : 0
|
|
);
|
|
}
|
|
}
|
|
|
|
if (toFolder) {
|
|
if (trashFolder === toFolder.fullName || spamFolder === toFolder.fullName) {
|
|
unseenCount = 0;
|
|
}
|
|
|
|
toFolder.messageCountAll(toFolder.messageCountAll() + uidForRemove.length);
|
|
if (0 < unseenCount) {
|
|
toFolder.messageCountUnread(toFolder.messageCountUnread() + unseenCount);
|
|
}
|
|
|
|
toFolder.actionBlink(true);
|
|
}
|
|
|
|
if (messages.length) {
|
|
if (copy) {
|
|
messages.forEach(item => item.checked(false));
|
|
} else {
|
|
MessagelistUserStore.isIncomplete(true);
|
|
|
|
messages.forEach(item => {
|
|
if (currentMessage && currentMessage.hash === item.hash) {
|
|
currentMessage = null;
|
|
MessageUserStore.message(null);
|
|
}
|
|
|
|
item.deleted(true);
|
|
});
|
|
|
|
setTimeout(() => messages.forEach(item => messageList.remove(item)), 350);
|
|
}
|
|
}
|
|
|
|
if (fromFolderFullName) {
|
|
setFolderHash(fromFolderFullName, '');
|
|
}
|
|
|
|
if (toFolderFullName) {
|
|
setFolderHash(toFolderFullName, '');
|
|
}
|
|
|
|
if (MessagelistUserStore.threadUid()) {
|
|
if (
|
|
messageList.length &&
|
|
!!messageList.find(item => !!(item && item.deleted() && item.uid == MessagelistUserStore.threadUid()))
|
|
) {
|
|
const message = messageList.find(item => item && !item.deleted());
|
|
let setHash;
|
|
if (!message) {
|
|
if (1 < MessagelistUserStore.page()) {
|
|
MessagelistUserStore.page(MessagelistUserStore.page() - 1);
|
|
setHash = 1;
|
|
} else {
|
|
MessagelistUserStore.threadUid(0);
|
|
rl.route.setHash(
|
|
mailBox(
|
|
FolderUserStore.currentFolderFullNameHash(),
|
|
MessagelistUserStore.pageBeforeThread(),
|
|
MessagelistUserStore.listSearch()
|
|
),
|
|
true,
|
|
true
|
|
);
|
|
}
|
|
} else if (MessagelistUserStore.threadUid() != message.uid) {
|
|
MessagelistUserStore.threadUid(message.uid);
|
|
setHash = 1;
|
|
}
|
|
if (setHash) {
|
|
rl.route.setHash(
|
|
mailBox(
|
|
FolderUserStore.currentFolderFullNameHash(),
|
|
MessagelistUserStore.page(),
|
|
MessagelistUserStore.listSearch(),
|
|
MessagelistUserStore.threadUid()
|
|
),
|
|
true,
|
|
true
|
|
);
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
MessagelistUserStore.reloadFlagsAndCachedMessage = () => {
|
|
MessagelistUserStore.forEach(message => MessageFlagsCache.initMessage(message));
|
|
MessageFlagsCache.initMessage(MessageUserStore.message());
|
|
};
|