2022-02-24 02:26:52 +08:00
|
|
|
import { isArray, arrayLength } from 'Common/Utils';
|
|
|
|
import {
|
|
|
|
MessageFlagsCache,
|
|
|
|
setFolderHash,
|
|
|
|
getFolderInboxName,
|
2022-06-07 17:54:19 +08:00
|
|
|
getFolderFromCacheList
|
2022-02-24 02:26:52 +08:00
|
|
|
} from 'Common/Cache';
|
|
|
|
import { SettingsUserStore } from 'Stores/User/Settings';
|
|
|
|
import { FolderUserStore } from 'Stores/User/Folder';
|
|
|
|
import { MessagelistUserStore } from 'Stores/User/Messagelist';
|
|
|
|
import { getNotification } from 'Common/Translator';
|
2023-01-09 19:28:07 +08:00
|
|
|
import { Settings } from 'Common/Globals';
|
2022-10-28 05:51:55 +08:00
|
|
|
import { serverRequest } from 'Common/Links';
|
2022-02-24 02:26:52 +08:00
|
|
|
|
|
|
|
import Remote from 'Remote/User/Fetch';
|
|
|
|
|
2023-02-01 19:21:31 +08:00
|
|
|
let refreshInterval,
|
|
|
|
// Default every 5 minutes
|
|
|
|
refreshFoldersInterval = 300000;
|
|
|
|
|
2022-02-24 02:26:52 +08:00
|
|
|
export const
|
|
|
|
|
2023-02-01 19:21:31 +08:00
|
|
|
setRefreshFoldersInterval = minutes => {
|
|
|
|
refreshFoldersInterval = Math.max(5, minutes) * 60000;
|
|
|
|
clearInterval(refreshInterval);
|
|
|
|
refreshInterval = setInterval(() => {
|
|
|
|
const cF = FolderUserStore.currentFolderFullName(),
|
|
|
|
iF = getFolderInboxName();
|
|
|
|
folderInformation(iF);
|
|
|
|
iF === cF || folderInformation(cF);
|
|
|
|
folderInformationMultiply();
|
|
|
|
}, refreshFoldersInterval);
|
|
|
|
},
|
|
|
|
|
2022-02-24 02:26:52 +08:00
|
|
|
sortFolders = folders => {
|
|
|
|
try {
|
|
|
|
let collator = new Intl.Collator(undefined, {numeric: true, sensitivity: 'base'});
|
|
|
|
folders.sort((a, b) =>
|
|
|
|
a.isInbox() ? -1 : (b.isInbox() ? 1 : collator.compare(a.fullName, b.fullName))
|
|
|
|
);
|
|
|
|
} catch (e) {
|
|
|
|
console.error(e);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param {Array=} aDisabled
|
|
|
|
* @param {Array=} aHeaderLines
|
|
|
|
* @param {Function=} fRenameCallback
|
2022-03-11 17:26:25 +08:00
|
|
|
* @param {Function=} fDisableCallback
|
2022-02-24 02:26:52 +08:00
|
|
|
* @param {boolean=} bNoSelectSelectable Used in FolderCreatePopupView
|
|
|
|
* @returns {Array}
|
|
|
|
*/
|
|
|
|
folderListOptionsBuilder = (
|
|
|
|
aDisabled,
|
|
|
|
aHeaderLines,
|
|
|
|
fRenameCallback,
|
|
|
|
fDisableCallback,
|
|
|
|
bNoSelectSelectable,
|
|
|
|
aList = FolderUserStore.folderList()
|
|
|
|
) => {
|
|
|
|
const
|
|
|
|
aResult = [],
|
|
|
|
sDeepPrefix = '\u00A0\u00A0\u00A0',
|
|
|
|
// FolderSystemPopupView should always be true
|
|
|
|
showUnsubscribed = fRenameCallback ? !SettingsUserStore.hideUnsubscribed() : true,
|
|
|
|
|
|
|
|
foldersWalk = folders => {
|
|
|
|
folders.forEach(oItem => {
|
|
|
|
if (showUnsubscribed || oItem.hasSubscriptions() || !oItem.exists) {
|
|
|
|
aResult.push({
|
|
|
|
id: oItem.fullName,
|
|
|
|
name:
|
|
|
|
sDeepPrefix.repeat(oItem.deep) +
|
|
|
|
fRenameCallback(oItem),
|
|
|
|
system: false,
|
|
|
|
disabled: !bNoSelectSelectable && (
|
|
|
|
!oItem.selectable() ||
|
|
|
|
aDisabled.includes(oItem.fullName) ||
|
|
|
|
fDisableCallback(oItem))
|
|
|
|
});
|
|
|
|
}
|
2022-10-10 19:52:56 +08:00
|
|
|
foldersWalk(oItem.subFolders());
|
2022-02-24 02:26:52 +08:00
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
fDisableCallback = fDisableCallback || (() => false);
|
|
|
|
fRenameCallback = fRenameCallback || (oItem => oItem.name());
|
|
|
|
isArray(aDisabled) || (aDisabled = []);
|
|
|
|
|
|
|
|
isArray(aHeaderLines) && aHeaderLines.forEach(line =>
|
|
|
|
aResult.push({
|
|
|
|
id: line[0],
|
|
|
|
name: line[1],
|
|
|
|
system: false,
|
|
|
|
disabled: false
|
|
|
|
})
|
|
|
|
);
|
|
|
|
|
|
|
|
foldersWalk(aList);
|
|
|
|
|
|
|
|
return aResult;
|
|
|
|
},
|
|
|
|
|
2022-08-23 03:52:00 +08:00
|
|
|
/**
|
|
|
|
* @param {string} folder
|
|
|
|
* @param {Array=} list = []
|
|
|
|
*/
|
|
|
|
folderInformation = (folder, list) => {
|
2022-09-02 17:52:07 +08:00
|
|
|
if (folder?.trim()) {
|
2023-01-31 19:47:21 +08:00
|
|
|
let count = 1;
|
|
|
|
const uids = [];
|
2023-01-09 19:28:07 +08:00
|
|
|
|
2023-01-31 19:47:21 +08:00
|
|
|
if (arrayLength(list)) {
|
2023-01-09 19:28:07 +08:00
|
|
|
list.forEach(messageListItem => {
|
|
|
|
MessageFlagsCache.getFor(folder, messageListItem.uid) || uids.push(messageListItem.uid);
|
2023-01-31 19:47:21 +08:00
|
|
|
messageListItem.threads.forEach(uid => MessageFlagsCache.getFor(folder, uid) || uids.push(uid));
|
2023-01-09 19:28:07 +08:00
|
|
|
});
|
2023-01-31 19:47:21 +08:00
|
|
|
count = uids.length;
|
2023-01-09 19:28:07 +08:00
|
|
|
}
|
|
|
|
|
2023-01-31 19:47:21 +08:00
|
|
|
if (count) {
|
2023-01-09 19:28:07 +08:00
|
|
|
Remote.request('FolderInformation', (iError, data) => {
|
2022-08-23 03:52:00 +08:00
|
|
|
if (!iError && data.Result) {
|
|
|
|
const result = data.Result,
|
2023-01-25 01:58:25 +08:00
|
|
|
folderFromCache = getFolderFromCacheList(result.folder);
|
2022-08-23 03:52:00 +08:00
|
|
|
if (folderFromCache) {
|
|
|
|
const oldHash = folderFromCache.hash,
|
|
|
|
unreadCountChange = (folderFromCache.unreadEmails() !== result.unreadEmails);
|
|
|
|
|
2023-02-14 17:11:25 +08:00
|
|
|
// folderFromCache.revivePropertiesFromJson(result);
|
2022-08-23 03:52:00 +08:00
|
|
|
folderFromCache.expires = Date.now();
|
2023-01-25 01:58:25 +08:00
|
|
|
folderFromCache.uidNext = result.uidNext;
|
|
|
|
folderFromCache.hash = result.hash;
|
2022-08-23 03:52:00 +08:00
|
|
|
folderFromCache.totalEmails(result.totalEmails);
|
|
|
|
folderFromCache.unreadEmails(result.unreadEmails);
|
|
|
|
|
2022-10-10 19:52:56 +08:00
|
|
|
unreadCountChange && MessageFlagsCache.clearFolder(folderFromCache.fullName);
|
2022-08-23 03:52:00 +08:00
|
|
|
|
2023-01-25 01:58:25 +08:00
|
|
|
if (result.messagesFlags.length) {
|
|
|
|
result.messagesFlags.forEach(message =>
|
|
|
|
MessageFlagsCache.setFor(folderFromCache.fullName, message.uid.toString(), message.flags)
|
2022-08-23 03:52:00 +08:00
|
|
|
);
|
|
|
|
|
|
|
|
MessagelistUserStore.reloadFlagsAndCachedMessage();
|
|
|
|
}
|
|
|
|
|
2022-12-29 20:40:46 +08:00
|
|
|
MessagelistUserStore.notifyNewMessages(folderFromCache.fullName, result.newMessages);
|
2022-08-23 03:52:00 +08:00
|
|
|
|
2023-01-25 01:58:25 +08:00
|
|
|
if (!oldHash || unreadCountChange || result.hash !== oldHash) {
|
2022-08-23 03:52:00 +08:00
|
|
|
if (folderFromCache.fullName === FolderUserStore.currentFolderFullName()) {
|
|
|
|
MessagelistUserStore.reload();
|
2023-02-14 17:11:25 +08:00
|
|
|
/*
|
2022-08-23 03:52:00 +08:00
|
|
|
} else if (getFolderInboxName() === folderFromCache.fullName) {
|
2023-01-09 21:06:33 +08:00
|
|
|
// Remote.messageList(null, {folder: getFolderFromCacheList(getFolderInboxName())}, true);
|
|
|
|
Remote.messageList(null, {folder: getFolderInboxName()}, true);
|
2023-02-14 17:11:25 +08:00
|
|
|
*/
|
2022-08-23 03:52:00 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2023-01-09 19:28:07 +08:00
|
|
|
}, {
|
2023-01-25 01:58:25 +08:00
|
|
|
folder: folder,
|
|
|
|
flagsUids: uids,
|
2023-01-31 19:47:21 +08:00
|
|
|
uidNext: getFolderFromCacheList(folder)?.uidNext || 0 // Used to check for new messages
|
2023-01-09 19:28:07 +08:00
|
|
|
});
|
|
|
|
} else if (SettingsUserStore.useThreads()) {
|
|
|
|
MessagelistUserStore.reloadFlagsAndCachedMessage();
|
|
|
|
}
|
2022-08-23 03:52:00 +08:00
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2022-02-24 02:26:52 +08:00
|
|
|
/**
|
|
|
|
* @param {boolean=} boot = false
|
|
|
|
*/
|
|
|
|
folderInformationMultiply = (boot = false) => {
|
|
|
|
const folders = FolderUserStore.getNextFolderNames(refreshFoldersInterval);
|
|
|
|
if (arrayLength(folders)) {
|
|
|
|
Remote.request('FolderInformationMultiply', (iError, oData) => {
|
|
|
|
if (!iError && arrayLength(oData.Result)) {
|
|
|
|
const utc = Date.now();
|
|
|
|
oData.Result.forEach(item => {
|
2023-01-25 01:58:25 +08:00
|
|
|
const folder = getFolderFromCacheList(item.folder);
|
2022-02-24 02:26:52 +08:00
|
|
|
|
|
|
|
if (folder) {
|
2022-06-07 17:54:19 +08:00
|
|
|
const oldHash = folder.hash,
|
|
|
|
unreadCountChange = folder.unreadEmails() !== item.unreadEmails;
|
2022-02-24 02:26:52 +08:00
|
|
|
|
2022-06-07 17:54:19 +08:00
|
|
|
// folder.revivePropertiesFromJson(item);
|
|
|
|
folder.expires = utc;
|
2023-01-25 01:58:25 +08:00
|
|
|
folder.hash = item.hash;
|
2022-06-03 19:47:04 +08:00
|
|
|
folder.totalEmails(item.totalEmails);
|
|
|
|
folder.unreadEmails(item.unreadEmails);
|
2022-02-24 02:26:52 +08:00
|
|
|
|
2022-10-10 19:52:56 +08:00
|
|
|
unreadCountChange && MessageFlagsCache.clearFolder(folder.fullName);
|
2022-02-24 02:26:52 +08:00
|
|
|
|
2023-01-25 01:58:25 +08:00
|
|
|
if (!oldHash || item.hash !== oldHash) {
|
2022-02-24 02:26:52 +08:00
|
|
|
if (folder.fullName === FolderUserStore.currentFolderFullName()) {
|
|
|
|
MessagelistUserStore.reload();
|
|
|
|
}
|
|
|
|
} else if (unreadCountChange
|
|
|
|
&& folder.fullName === FolderUserStore.currentFolderFullName()
|
|
|
|
&& MessagelistUserStore.length) {
|
2022-08-23 03:52:00 +08:00
|
|
|
folderInformation(folder.fullName, MessagelistUserStore());
|
2022-02-24 02:26:52 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2022-10-10 19:52:56 +08:00
|
|
|
boot && setTimeout(() => folderInformationMultiply(true), 2000);
|
2022-02-24 02:26:52 +08:00
|
|
|
}
|
|
|
|
}, {
|
2023-01-26 17:41:55 +08:00
|
|
|
folders: folders
|
2022-02-24 02:26:52 +08:00
|
|
|
});
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
moveOrDeleteResponseHelper = (iError, oData) => {
|
|
|
|
if (iError) {
|
|
|
|
setFolderHash(FolderUserStore.currentFolderFullName(), '');
|
|
|
|
alert(getNotification(iError));
|
|
|
|
} else if (FolderUserStore.currentFolder()) {
|
|
|
|
if (2 === arrayLength(oData.Result)) {
|
|
|
|
setFolderHash(oData.Result[0], oData.Result[1]);
|
|
|
|
} else {
|
|
|
|
setFolderHash(FolderUserStore.currentFolderFullName(), '');
|
|
|
|
}
|
|
|
|
MessagelistUserStore.reload(!MessagelistUserStore.length);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
messagesMoveHelper = (fromFolderFullName, toFolderFullName, uidsForMove) => {
|
|
|
|
const
|
|
|
|
sSpamFolder = FolderUserStore.spamFolder(),
|
|
|
|
isSpam = sSpamFolder === toFolderFullName,
|
|
|
|
isHam = !isSpam && sSpamFolder === fromFolderFullName && getFolderInboxName() === toFolderFullName;
|
|
|
|
|
2022-09-02 15:56:31 +08:00
|
|
|
Remote.abort('MessageList').request('MessageMove',
|
2022-02-24 02:26:52 +08:00
|
|
|
moveOrDeleteResponseHelper,
|
|
|
|
{
|
2023-01-26 17:41:55 +08:00
|
|
|
fromFolder: fromFolderFullName,
|
|
|
|
toFolder: toFolderFullName,
|
|
|
|
uids: [...uidsForMove].join(','),
|
|
|
|
markAsRead: (isSpam || FolderUserStore.trashFolder() === toFolderFullName) ? 1 : 0,
|
|
|
|
learning: isSpam ? 'SPAM' : isHam ? 'HAM' : ''
|
2022-09-02 15:56:31 +08:00
|
|
|
}
|
2022-02-24 02:26:52 +08:00
|
|
|
);
|
|
|
|
},
|
|
|
|
|
|
|
|
messagesDeleteHelper = (sFromFolderFullName, aUidForRemove) => {
|
2022-09-02 15:56:31 +08:00
|
|
|
Remote.abort('MessageList').request('MessageDelete',
|
2022-02-24 02:26:52 +08:00
|
|
|
moveOrDeleteResponseHelper,
|
|
|
|
{
|
2023-01-25 01:58:25 +08:00
|
|
|
folder: sFromFolderFullName,
|
2023-01-26 17:41:55 +08:00
|
|
|
uids: [...aUidForRemove].join(',')
|
2022-09-02 15:56:31 +08:00
|
|
|
}
|
2022-02-24 02:26:52 +08:00
|
|
|
);
|
|
|
|
},
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @param {string} sFromFolderFullName
|
2022-09-28 05:46:13 +08:00
|
|
|
* @param {Set} oUids
|
2022-02-24 02:26:52 +08:00
|
|
|
* @param {string} sToFolderFullName
|
|
|
|
* @param {boolean=} bCopy = false
|
|
|
|
*/
|
2022-09-28 05:46:13 +08:00
|
|
|
moveMessagesToFolder = (sFromFolderFullName, oUids, sToFolderFullName, bCopy) => {
|
|
|
|
if (sFromFolderFullName !== sToFolderFullName && oUids?.size) {
|
2022-02-24 02:26:52 +08:00
|
|
|
const oFromFolder = getFolderFromCacheList(sFromFolderFullName),
|
|
|
|
oToFolder = getFolderFromCacheList(sToFolderFullName);
|
|
|
|
|
|
|
|
if (oFromFolder && oToFolder) {
|
2022-10-10 19:52:56 +08:00
|
|
|
bCopy
|
|
|
|
? Remote.request('MessageCopy', null, {
|
2023-01-26 17:41:55 +08:00
|
|
|
fromFolder: oFromFolder.fullName,
|
|
|
|
toFolder: oToFolder.fullName,
|
|
|
|
uids: [...oUids].join(',')
|
2022-10-10 19:52:56 +08:00
|
|
|
})
|
|
|
|
: messagesMoveHelper(oFromFolder.fullName, oToFolder.fullName, oUids);
|
2022-02-24 02:26:52 +08:00
|
|
|
|
2022-09-28 05:46:13 +08:00
|
|
|
MessagelistUserStore.removeMessagesFromList(oFromFolder.fullName, oUids, oToFolder.fullName, bCopy);
|
2022-02-24 02:26:52 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
2022-10-28 05:51:55 +08:00
|
|
|
},
|
|
|
|
|
|
|
|
dropFilesInFolder = (sFolderFullName, files) => {
|
|
|
|
let count = 0,
|
|
|
|
fn = () => 0 == --count
|
|
|
|
&& FolderUserStore.currentFolderFullName() == sFolderFullName
|
|
|
|
&& MessagelistUserStore.reload(true, true);
|
|
|
|
for (const file of files) {
|
|
|
|
if ('message/rfc822' === file.type) {
|
|
|
|
++count;
|
|
|
|
let data = new FormData;
|
2023-01-25 01:58:25 +08:00
|
|
|
data.append('folder', sFolderFullName);
|
2023-01-26 17:41:55 +08:00
|
|
|
data.append('appendFile', file);
|
2022-10-28 05:51:55 +08:00
|
|
|
data.XToken = Settings.app('token');
|
|
|
|
fetch(serverRequest('Append'), {
|
|
|
|
method: 'POST',
|
|
|
|
mode: 'same-origin',
|
|
|
|
cache: 'no-cache',
|
|
|
|
redirect: 'error',
|
|
|
|
referrerPolicy: 'no-referrer',
|
|
|
|
credentials: 'same-origin',
|
|
|
|
body: data
|
|
|
|
})
|
|
|
|
.then(fn)
|
|
|
|
.catch(fn);
|
|
|
|
}
|
|
|
|
}
|
2022-02-24 02:26:52 +08:00
|
|
|
};
|