snappymail/dev/App/User.js

847 lines
23 KiB
JavaScript
Raw Normal View History

2021-01-26 18:46:30 +08:00
import 'External/User/ko';
import { isArray, arrayLength, pString, forEachObjectValue } from 'Common/Utils';
2021-11-05 17:20:06 +08:00
import { delegateRunOnDestroy, mailToHelper, setLayoutResizer } from 'Common/UtilsUser';
2016-06-07 05:57:52 +08:00
import {
2019-07-05 03:19:24 +08:00
Capa,
Notification,
Scope
2021-01-25 05:58:06 +08:00
} from 'Common/Enums';
import {
2019-07-05 03:19:24 +08:00
FolderType,
SetSystemFoldersNotification,
MessageSetAction,
2020-08-14 04:58:41 +08:00
ClientSideKeyName
2021-01-25 05:58:06 +08:00
} from 'Common/EnumsUser';
2016-06-07 05:57:52 +08:00
import {
doc,
elementById,
createElement,
$htmlCL,
Settings,
2021-03-10 18:44:48 +08:00
SettingsGet,
leftPanelDisabled
} from 'Common/Globals';
2016-06-07 05:57:52 +08:00
2019-07-05 03:19:24 +08:00
import { UNUSED_OPTION_VALUE } from 'Common/Consts';
2016-08-22 05:30:34 +08:00
import {
MessageFlagsCache,
2019-07-05 03:19:24 +08:00
setFolderHash,
getFolderHash,
getFolderInboxName,
getFolderFromCacheList
2016-08-22 05:30:34 +08:00
} from 'Common/Cache';
import {
2019-07-05 03:19:24 +08:00
mailBox,
root,
openPgpWorkerJs,
openPgpJs
2016-08-22 05:30:34 +08:00
} from 'Common/Links';
2019-07-05 03:19:24 +08:00
import { getNotification, i18n } from 'Common/Translator';
2015-11-19 01:32:29 +08:00
import { SettingsUserStore } from 'Stores/User/Settings';
import { NotificationUserStore } from 'Stores/User/Notification';
import { AccountUserStore } from 'Stores/User/Account';
import { ContactUserStore } from 'Stores/User/Contact';
import { IdentityUserStore } from 'Stores/User/Identity';
import { FolderUserStore } from 'Stores/User/Folder';
import { PgpUserStore } from 'Stores/User/Pgp';
import { MessageUserStore } from 'Stores/User/Message';
import { ThemeStore } from 'Stores/Theme';
2015-11-19 01:32:29 +08:00
2016-06-17 07:23:49 +08:00
import * as Local from 'Storage/Client';
2015-11-19 01:32:29 +08:00
import Remote from 'Remote/User/Fetch';
2015-11-19 01:32:29 +08:00
2019-07-05 03:19:24 +08:00
import { EmailModel } from 'Model/Email';
import { AccountModel } from 'Model/Account';
import { IdentityModel } from 'Model/Identity';
import { OpenPgpKeyModel } from 'Model/OpenPgpKey';
2015-11-19 01:32:29 +08:00
2019-07-05 03:19:24 +08:00
import { LoginUserScreen } from 'Screen/User/Login';
import { MailBoxUserScreen } from 'Screen/User/MailBox';
import { SettingsUserScreen } from 'Screen/User/Settings';
2016-07-07 07:11:13 +08:00
import { startScreens, showScreenPopup, arePopupsVisible } from 'Knoin/Knoin';
2015-11-19 01:32:29 +08:00
2019-07-05 03:19:24 +08:00
import { AbstractApp } from 'App/Abstract';
2015-11-19 01:32:29 +08:00
import { ComposePopupView } from 'View/Popup/Compose';
import { FolderSystemPopupView } from 'View/Popup/FolderSystem';
import { AskPopupView } from 'View/Popup/Ask';
2021-07-19 20:26:32 +08:00
import { timeToNode } from 'Common/Momentor';
2021-03-18 20:52:56 +08:00
// Every 5 minutes
const refreshFolders = 300000;
2019-07-05 03:19:24 +08:00
class AppUser extends AbstractApp {
2016-07-16 05:29:42 +08:00
constructor() {
2015-11-19 01:32:29 +08:00
super(Remote);
2016-06-28 04:54:38 +08:00
this.moveCache = {};
this.moveOrDeleteResponseHelper = this.moveOrDeleteResponseHelper.bind(this);
this.messagesMoveTrigger = this.messagesMoveTrigger.debounce(500);
// wakeUp
2020-08-14 04:58:41 +08:00
const interval = 3600000; // 60m
2020-09-04 23:07:35 +08:00
var lastTime = Date.now();
setInterval(() => {
2020-09-04 23:07:35 +08:00
const currentTime = Date.now();
if (currentTime > (lastTime + interval + 1000)) {
2021-03-18 21:48:21 +08:00
Remote.jsVersion(iError => {
if (100 < iError) {
2019-07-05 03:19:24 +08:00
this.reload();
}
}, Settings.app('version'));
}
lastTime = currentTime;
}, interval);
2014-08-22 23:08:56 +08:00
const fn = (ev=>$htmlCL.toggle('rl-ctrl-key-pressed', ev.ctrlKey)).debounce(500);
['keydown','keyup'].forEach(t => doc.addEventListener(t, fn));
shortcuts.add('escape,enter', '', Scope.All, () => rl.Dropdowns.detectVisibility());
}
2016-05-22 20:27:50 +08:00
reload() {
(Settings.app('inIframe') ? parent : window).location.reload();
2016-05-22 20:27:50 +08:00
}
2015-11-19 01:32:29 +08:00
reloadFlagsCurrentMessageListAndMessageFromCache() {
2021-03-12 23:54:37 +08:00
MessageUserStore.list.forEach(message =>
MessageFlagsCache.initMessage(message)
);
MessageFlagsCache.initMessage(MessageUserStore.message());
2021-03-12 23:54:37 +08:00
MessageUserStore.messageViewTrigger(!MessageUserStore.messageViewTrigger());
2015-11-19 01:32:29 +08:00
}
2014-08-20 23:03:12 +08:00
/**
* @param {boolean=} bDropPagePosition = false
* @param {boolean=} bDropCurrenFolderCache = false
*/
2015-11-19 01:32:29 +08:00
reloadMessageList(bDropPagePosition = false, bDropCurrenFolderCache = false) {
2021-03-12 23:54:37 +08:00
let iOffset = (MessageUserStore.listPage() - 1) * SettingsUserStore.messagesPerPage();
2015-11-19 01:32:29 +08:00
2019-07-05 03:19:24 +08:00
if (bDropCurrenFolderCache) {
setFolderHash(FolderUserStore.currentFolderFullNameRaw(), '');
}
2014-08-20 23:03:12 +08:00
2019-07-05 03:19:24 +08:00
if (bDropPagePosition) {
2021-03-12 23:54:37 +08:00
MessageUserStore.listPage(1);
MessageUserStore.listPageBeforeThread(1);
2014-08-20 23:03:12 +08:00
iOffset = 0;
2015-04-22 05:01:29 +08:00
rl.route.setHash(
2019-07-05 03:19:24 +08:00
mailBox(
FolderUserStore.currentFolderFullNameHash(),
2021-03-12 23:54:37 +08:00
MessageUserStore.listPage(),
MessageUserStore.listSearch(),
MessageUserStore.listThreadUid()
2019-07-05 03:19:24 +08:00
),
true,
true
);
}
2021-03-12 23:54:37 +08:00
MessageUserStore.listLoading(true);
MessageUserStore.listError('');
Remote.messageList(
(iError, oData, bCached) => {
if (iError) {
if (Notification.RequestAborted !== iError) {
MessageUserStore.list([]);
MessageUserStore.listError(getNotification(iError));
}
} else {
MessageUserStore.setMessageList(oData, bCached);
}
MessageUserStore.listLoading(false);
},
{
Folder: FolderUserStore.currentFolderFullNameRaw(),
Offset: iOffset,
Limit: SettingsUserStore.messagesPerPage(),
Search: MessageUserStore.listSearch(),
2021-03-30 15:10:43 +08:00
ThreadUid: MessageUserStore.listThreadUid()
}
);
2015-11-19 01:32:29 +08:00
}
2015-11-19 01:32:29 +08:00
recacheInboxMessageList() {
Remote.messageList(null, {Folder: getFolderInboxName()}, true);
2015-11-19 01:32:29 +08:00
}
2015-11-19 01:32:29 +08:00
messagesMoveTrigger() {
const sTrashFolder = FolderUserStore.trashFolder(),
sSpamFolder = FolderUserStore.spamFolder();
forEachObjectValue(this.moveCache, item => {
const isSpam = sSpamFolder === item.To,
isTrash = sTrashFolder === item.To,
isHam = !isSpam && sSpamFolder === item.From && getFolderInboxName() === item.To;
Remote.messagesMove(
this.moveOrDeleteResponseHelper,
item.From,
item.To,
item.Uid,
isSpam ? 'SPAM' : isHam ? 'HAM' : '',
isSpam || isTrash
);
});
2014-03-20 00:18:28 +08:00
this.moveCache = {};
2015-11-19 01:32:29 +08:00
}
messagesMoveHelper(fromFolderFullNameRaw, toFolderFullNameRaw, uidsForMove) {
const hash = '$$' + fromFolderFullNameRaw + '$$' + toFolderFullNameRaw + '$$';
2019-07-05 03:19:24 +08:00
if (!this.moveCache[hash]) {
this.moveCache[hash] = {
From: fromFolderFullNameRaw,
To: toFolderFullNameRaw,
2016-04-21 01:12:51 +08:00
Uid: []
2014-08-20 23:03:12 +08:00
};
2014-03-20 00:18:28 +08:00
}
this.moveCache[hash].Uid = this.moveCache[hash].Uid.concat(uidsForMove).unique();
2014-08-20 23:03:12 +08:00
this.messagesMoveTrigger();
2015-11-19 01:32:29 +08:00
}
2015-11-19 01:32:29 +08:00
messagesCopyHelper(sFromFolderFullNameRaw, sToFolderFullNameRaw, aUidForCopy) {
2019-07-05 03:19:24 +08:00
Remote.messagesCopy(this.moveOrDeleteResponseHelper, sFromFolderFullNameRaw, sToFolderFullNameRaw, aUidForCopy);
2015-11-19 01:32:29 +08:00
}
2014-08-20 23:03:12 +08:00
2015-11-19 01:32:29 +08:00
messagesDeleteHelper(sFromFolderFullNameRaw, aUidForRemove) {
2019-07-05 03:19:24 +08:00
Remote.messagesDelete(this.moveOrDeleteResponseHelper, sFromFolderFullNameRaw, aUidForRemove);
2015-11-19 01:32:29 +08:00
}
moveOrDeleteResponseHelper(iError, oData) {
if (iError) {
setFolderHash(FolderUserStore.currentFolderFullNameRaw(), '');
alert(getNotification(iError));
} else if (FolderUserStore.currentFolder()) {
2021-07-22 03:34:17 +08:00
if (2 === arrayLength(oData.Result)) {
2016-08-22 05:30:34 +08:00
setFolderHash(oData.Result[0], oData.Result[1]);
2019-07-05 03:19:24 +08:00
} else {
setFolderHash(FolderUserStore.currentFolderFullNameRaw(), '');
}
2021-03-12 23:54:37 +08:00
this.reloadMessageList(!MessageUserStore.list.length);
2014-03-20 00:18:28 +08:00
}
2015-11-19 01:32:29 +08:00
}
2014-03-20 00:18:28 +08:00
2014-08-20 23:03:12 +08:00
/**
* @param {string} sFromFolderFullNameRaw
* @param {Array} aUidForRemove
*/
2015-11-19 01:32:29 +08:00
deleteMessagesFromFolderWithoutCheck(sFromFolderFullNameRaw, aUidForRemove) {
2014-08-20 23:03:12 +08:00
this.messagesDeleteHelper(sFromFolderFullNameRaw, aUidForRemove);
MessageUserStore.removeMessagesFromList(sFromFolderFullNameRaw, aUidForRemove);
2015-11-19 01:32:29 +08:00
}
2014-08-20 23:03:12 +08:00
/**
* @param {number} iDeleteType
* @param {string} sFromFolderFullNameRaw
* @param {Array} aUidForRemove
* @param {boolean=} bUseFolder = true
*/
2015-11-19 01:32:29 +08:00
deleteMessagesFromFolder(iDeleteType, sFromFolderFullNameRaw, aUidForRemove, bUseFolder) {
2019-07-05 03:19:24 +08:00
let oMoveFolder = null,
2016-06-30 08:02:45 +08:00
nSetSystemFoldersNotification = null;
2014-03-20 00:18:28 +08:00
2019-07-05 03:19:24 +08:00
switch (iDeleteType) {
2016-06-07 05:57:52 +08:00
case FolderType.Spam:
oMoveFolder = getFolderFromCacheList(FolderUserStore.spamFolder());
2016-06-07 05:57:52 +08:00
nSetSystemFoldersNotification = SetSystemFoldersNotification.Spam;
2014-08-20 23:03:12 +08:00
break;
2016-06-07 05:57:52 +08:00
case FolderType.NotSpam:
2016-08-22 05:30:34 +08:00
oMoveFolder = getFolderFromCacheList(getFolderInboxName());
2014-08-20 23:03:12 +08:00
break;
2016-06-07 05:57:52 +08:00
case FolderType.Trash:
oMoveFolder = getFolderFromCacheList(FolderUserStore.trashFolder());
2016-06-07 05:57:52 +08:00
nSetSystemFoldersNotification = SetSystemFoldersNotification.Trash;
2014-08-20 23:03:12 +08:00
break;
2016-06-07 05:57:52 +08:00
case FolderType.Archive:
oMoveFolder = getFolderFromCacheList(FolderUserStore.archiveFolder());
2016-06-07 05:57:52 +08:00
nSetSystemFoldersNotification = SetSystemFoldersNotification.Archive;
2014-08-20 23:03:12 +08:00
break;
2016-06-30 08:02:45 +08:00
// no default
2014-08-20 23:03:12 +08:00
}
bUseFolder = undefined === bUseFolder ? true : !!bUseFolder;
2019-07-05 03:19:24 +08:00
if (bUseFolder) {
if (
(FolderType.Spam === iDeleteType && UNUSED_OPTION_VALUE === FolderUserStore.spamFolder()) ||
(FolderType.Trash === iDeleteType && UNUSED_OPTION_VALUE === FolderUserStore.trashFolder()) ||
(FolderType.Archive === iDeleteType && UNUSED_OPTION_VALUE === FolderUserStore.archiveFolder())
2019-07-05 03:19:24 +08:00
) {
2014-08-20 23:03:12 +08:00
bUseFolder = false;
}
}
2014-08-20 23:03:12 +08:00
2019-07-05 03:19:24 +08:00
if (!oMoveFolder && bUseFolder) {
showScreenPopup(FolderSystemPopupView, [nSetSystemFoldersNotification]);
2019-07-05 03:19:24 +08:00
} else if (
!bUseFolder ||
(FolderType.Trash === iDeleteType &&
(sFromFolderFullNameRaw === FolderUserStore.spamFolder()
|| sFromFolderFullNameRaw === FolderUserStore.trashFolder()))
2019-07-05 03:19:24 +08:00
) {
showScreenPopup(AskPopupView, [
2019-07-05 03:19:24 +08:00
i18n('POPUPS_ASK/DESC_WANT_DELETE_MESSAGES'),
() => {
this.messagesDeleteHelper(sFromFolderFullNameRaw, aUidForRemove);
MessageUserStore.removeMessagesFromList(sFromFolderFullNameRaw, aUidForRemove);
2019-07-05 03:19:24 +08:00
}
]);
} else if (oMoveFolder) {
2014-08-20 23:03:12 +08:00
this.messagesMoveHelper(sFromFolderFullNameRaw, oMoveFolder.fullNameRaw, aUidForRemove);
MessageUserStore.removeMessagesFromList(sFromFolderFullNameRaw, aUidForRemove, oMoveFolder.fullNameRaw);
2014-08-20 23:03:12 +08:00
}
2015-11-19 01:32:29 +08:00
}
2014-08-20 23:03:12 +08:00
/**
* @param {string} sFromFolderFullNameRaw
* @param {Array} aUidForMove
* @param {string} sToFolderFullNameRaw
* @param {boolean=} bCopy = false
*/
2015-11-19 01:32:29 +08:00
moveMessagesToFolder(sFromFolderFullNameRaw, aUidForMove, sToFolderFullNameRaw, bCopy) {
2021-07-22 03:34:17 +08:00
if (sFromFolderFullNameRaw !== sToFolderFullNameRaw && arrayLength(aUidForMove)) {
2019-07-05 03:19:24 +08:00
const oFromFolder = getFolderFromCacheList(sFromFolderFullNameRaw),
2016-08-22 05:30:34 +08:00
oToFolder = getFolderFromCacheList(sToFolderFullNameRaw);
2019-07-05 03:19:24 +08:00
if (oFromFolder && oToFolder) {
if (undefined === bCopy ? false : !!bCopy) {
2014-08-20 23:03:12 +08:00
this.messagesCopyHelper(oFromFolder.fullNameRaw, oToFolder.fullNameRaw, aUidForMove);
2019-07-05 03:19:24 +08:00
} else {
2014-08-20 23:03:12 +08:00
this.messagesMoveHelper(oFromFolder.fullNameRaw, oToFolder.fullNameRaw, aUidForMove);
2014-03-21 07:47:13 +08:00
}
MessageUserStore.removeMessagesFromList(oFromFolder.fullNameRaw, aUidForMove, oToFolder.fullNameRaw, bCopy);
2014-08-20 23:03:12 +08:00
return true;
}
}
2014-08-20 23:03:12 +08:00
return false;
2015-11-19 01:32:29 +08:00
}
2014-08-20 23:03:12 +08:00
/**
2015-11-19 01:32:29 +08:00
* @param {Function=} callback = null
2014-08-20 23:03:12 +08:00
*/
2015-11-19 01:32:29 +08:00
foldersReload(callback = null) {
Remote.foldersReload(callback);
2015-11-19 01:32:29 +08:00
}
foldersPromisesActionHelper(promise, errorDefCode) {
Remote.abort('Folders')
.fastResolve(true)
2015-11-19 01:32:29 +08:00
.then(() => promise)
2019-07-05 03:19:24 +08:00
.then(
() => Remote.foldersReloadWithTimeout(),
2021-08-25 18:00:50 +08:00
error => {
FolderUserStore.folderListError(getNotification(error.code, '', errorDefCode) + '.\n' + error.message);
Remote.foldersReloadWithTimeout();
2019-07-05 03:19:24 +08:00
}
);
2015-11-19 01:32:29 +08:00
}
reloadOpenPgpKeys() {
if (PgpUserStore.capaOpenPGP()) {
2019-07-05 03:19:24 +08:00
const keys = [],
email = new EmailModel(),
openpgpKeyring = PgpUserStore.openpgpKeyring,
openpgpKeys = openpgpKeyring ? openpgpKeyring.getAllKeys() : [];
openpgpKeys.forEach((oItem, iIndex) => {
2019-07-05 03:19:24 +08:00
if (oItem && oItem.primaryKey) {
const aEmails = [],
aUsers = [],
primaryUser = oItem.getPrimaryUser(),
2019-07-05 03:19:24 +08:00
user =
primaryUser && primaryUser.user
? primaryUser.user.userId.userid
: oItem.users && oItem.users[0]
? oItem.users[0].userId.userid
: '';
if (oItem.users) {
oItem.users.forEach(item => {
2019-07-05 03:19:24 +08:00
if (item.userId) {
email.clear();
2017-09-28 01:58:15 +08:00
email.parse(item.userId.userid);
2019-07-05 03:19:24 +08:00
if (email.validate()) {
aEmails.push(email.email);
2016-05-24 01:33:01 +08:00
aUsers.push(item.userId.userid);
}
}
});
}
2019-07-05 03:19:24 +08:00
if (aEmails.length) {
keys.push(
new OpenPgpKeyModel(
iIndex,
oItem.primaryKey.getFingerprint(),
oItem.primaryKey
.getKeyId()
.toHex()
.toLowerCase(),
oItem.getKeyIds()
.map(item => (item && item.toHex ? item.toHex() : null))
.validUnique(),
2019-07-05 03:19:24 +08:00
aUsers,
aEmails,
oItem.isPrivate(),
oItem.armor(),
user
)
2014-08-20 23:03:12 +08:00
);
}
}
});
delegateRunOnDestroy(PgpUserStore.openpgpkeys());
PgpUserStore.openpgpkeys(keys);
}
2015-11-19 01:32:29 +08:00
}
2014-08-20 23:03:12 +08:00
accountsAndIdentities() {
AccountUserStore.loading(true);
IdentityUserStore.loading(true);
Remote.accountsAndIdentities((iError, oData) => {
AccountUserStore.loading(false);
IdentityUserStore.loading(false);
2021-03-18 21:48:21 +08:00
if (!iError) {
2019-07-05 03:19:24 +08:00
const counts = {},
sAccountEmail = AccountUserStore.email();
2021-03-10 18:44:48 +08:00
let parentEmail = SettingsGet('ParentEmail') || sAccountEmail;
if (isArray(oData.Result.Accounts)) {
AccountUserStore.accounts.forEach(oAccount =>
counts[oAccount.email] = oAccount.count()
);
delegateRunOnDestroy(AccountUserStore.accounts());
AccountUserStore.accounts(
oData.Result.Accounts.map(
sValue => new AccountModel(sValue, sValue !== parentEmail, counts[sValue] || 0)
2019-07-05 03:19:24 +08:00
)
);
2014-08-20 23:03:12 +08:00
}
if (isArray(oData.Result.Identities)) {
delegateRunOnDestroy(IdentityUserStore());
2015-01-29 05:24:58 +08:00
IdentityUserStore(
oData.Result.Identities.map(identityData => {
2019-07-05 03:19:24 +08:00
const id = pString(identityData.Id),
email = pString(identityData.Email),
identity = new IdentityModel(id, email);
2013-12-07 06:45:46 +08:00
2019-07-05 03:19:24 +08:00
identity.name(pString(identityData.Name));
identity.replyTo(pString(identityData.ReplyTo));
identity.bcc(pString(identityData.Bcc));
identity.signature(pString(identityData.Signature));
identity.signatureInsertBefore(!!identityData.SignatureInsertBefore);
2013-12-07 06:45:46 +08:00
2019-07-05 03:19:24 +08:00
return identity;
})
);
}
}
2014-08-20 23:03:12 +08:00
});
2015-11-19 01:32:29 +08:00
}
2014-08-20 23:03:12 +08:00
/**
2015-11-19 01:32:29 +08:00
* @param {string} folder
* @param {Array=} list = []
2014-08-20 23:03:12 +08:00
*/
2015-11-19 01:32:29 +08:00
folderInformation(folder, list) {
if (folder && folder.trim()) {
2019-07-05 03:19:24 +08:00
Remote.folderInformation(
(iError, data) => {
if (!iError && data.Result) {
const result = data.Result,
hash = getFolderHash(result.Folder),
folderFromCache = getFolderFromCacheList(result.Folder);
if (folderFromCache) {
2021-03-18 20:52:56 +08:00
folderFromCache.expires = Date.now();
setFolderHash(result.Folder, result.Hash);
folderFromCache.messageCountAll(result.MessageCount);
2019-07-05 03:19:24 +08:00
let unreadCountChange = (folderFromCache.messageCountUnread() !== result.MessageUnseenCount);
2014-08-20 23:03:12 +08:00
folderFromCache.messageCountUnread(result.MessageUnseenCount);
2014-08-20 23:03:12 +08:00
if (unreadCountChange) {
MessageFlagsCache.clearFolder(folderFromCache.fullNameRaw);
}
2014-08-20 23:03:12 +08:00
if (result.Flags.length) {
result.Flags.forEach(flags =>
MessageFlagsCache.storeByFolderAndUid(folderFromCache.fullNameRaw, flags.Uid.toString(), [
!!flags.IsUnseen,
!!flags.IsFlagged,
!!flags.IsAnswered,
!!flags.IsForwarded,
!!flags.IsReadReceipt
])
);
2019-07-05 03:19:24 +08:00
this.reloadFlagsCurrentMessageListAndMessageFromCache();
}
MessageUserStore.initUidNextAndNewMessages(
folderFromCache.fullNameRaw,
result.UidNext,
result.NewMessages
);
if (!hash || unreadCountChange || result.Hash !== hash) {
if (folderFromCache.fullNameRaw === FolderUserStore.currentFolderFullNameRaw()) {
this.reloadMessageList();
} else if (getFolderInboxName() === folderFromCache.fullNameRaw) {
this.recacheInboxMessageList();
2014-08-20 23:03:12 +08:00
}
}
}
}
2019-07-05 03:19:24 +08:00
},
folder,
list
);
2014-08-20 23:03:12 +08:00
}
2016-04-21 01:12:51 +08:00
}
2014-08-20 23:03:12 +08:00
/**
2015-11-19 01:32:29 +08:00
* @param {boolean=} boot = false
2014-08-20 23:03:12 +08:00
*/
2015-11-19 01:32:29 +08:00
folderInformationMultiply(boot = false) {
2021-03-18 20:52:56 +08:00
const folders = FolderUserStore.getNextFolderNames(refreshFolders);
2021-07-22 03:34:17 +08:00
if (arrayLength(folders)) {
Remote.folderInformationMultiply((iError, oData) => {
if (!iError && arrayLength(oData.Result)) {
const utc = Date.now();
oData.Result.forEach(item => {
const hash = getFolderHash(item.Folder),
folder = getFolderFromCacheList(item.Folder);
if (folder) {
2021-03-18 20:52:56 +08:00
folder.expires = utc;
setFolderHash(item.Folder, item.Hash);
folder.messageCountAll(item.MessageCount);
let unreadCountChange = folder.messageCountUnread() !== item.MessageUnseenCount;
folder.messageCountUnread(item.MessageUnseenCount);
if (unreadCountChange) {
MessageFlagsCache.clearFolder(folder.fullNameRaw);
2014-08-20 23:03:12 +08:00
}
if (!hash || item.Hash !== hash) {
if (folder.fullNameRaw === FolderUserStore.currentFolderFullNameRaw()) {
this.reloadMessageList();
}
} else if (unreadCountChange
&& folder.fullNameRaw === FolderUserStore.currentFolderFullNameRaw()
&& MessageUserStore.list.length) {
this.folderInformation(folder.fullNameRaw, MessageUserStore.list());
}
2014-08-20 23:03:12 +08:00
}
});
if (boot) {
setTimeout(() => this.folderInformationMultiply(true), 2000);
2014-08-20 23:03:12 +08:00
}
}
2015-11-19 01:32:29 +08:00
}, folders);
}
2016-04-21 01:12:51 +08:00
}
2014-08-20 23:03:12 +08:00
2015-03-06 08:42:40 +08:00
/**
* @param {string} sFolderFullNameRaw
* @param {number} iSetAction
* @param {Array=} messages = null
2015-03-06 08:42:40 +08:00
*/
2016-12-15 05:56:17 +08:00
messageListAction(sFolderFullNameRaw, iSetAction, messages) {
2019-07-05 03:19:24 +08:00
let folder = null,
alreadyUnread = 0,
rootUids = [];
2015-03-06 08:42:40 +08:00
if (undefined === messages || !messages) {
2021-03-12 23:54:37 +08:00
messages = MessageUserStore.listChecked();
2015-03-06 08:42:40 +08:00
}
rootUids = messages.map(oMessage => oMessage && oMessage.uid ? oMessage.uid : null)
.validUnique();
2015-03-06 08:42:40 +08:00
if (sFolderFullNameRaw && rootUids.length) {
2019-07-05 03:19:24 +08:00
switch (iSetAction) {
2016-06-07 05:57:52 +08:00
case MessageSetAction.SetSeen:
rootUids.forEach(sSubUid =>
alreadyUnread += MessageFlagsCache.storeBySetAction(sFolderFullNameRaw, sSubUid, iSetAction)
);
2015-03-06 08:42:40 +08:00
2016-08-22 05:30:34 +08:00
folder = getFolderFromCacheList(sFolderFullNameRaw);
2019-07-05 03:19:24 +08:00
if (folder) {
folder.messageCountUnread(folder.messageCountUnread() - alreadyUnread);
2015-03-06 08:42:40 +08:00
}
2021-08-13 15:58:43 +08:00
Remote.messageSetSeen(()=>0, sFolderFullNameRaw, rootUids, true);
2015-03-06 08:42:40 +08:00
break;
2016-06-07 05:57:52 +08:00
case MessageSetAction.UnsetSeen:
rootUids.forEach(sSubUid =>
alreadyUnread += MessageFlagsCache.storeBySetAction(sFolderFullNameRaw, sSubUid, iSetAction)
);
2015-03-06 08:42:40 +08:00
2016-08-22 05:30:34 +08:00
folder = getFolderFromCacheList(sFolderFullNameRaw);
2019-07-05 03:19:24 +08:00
if (folder) {
folder.messageCountUnread(folder.messageCountUnread() - alreadyUnread + rootUids.length);
2015-03-06 08:42:40 +08:00
}
2021-08-13 15:58:43 +08:00
Remote.messageSetSeen(()=>0, sFolderFullNameRaw, rootUids, false);
2015-03-06 08:42:40 +08:00
break;
2016-06-07 05:57:52 +08:00
case MessageSetAction.SetFlag:
rootUids.forEach(sSubUid =>
MessageFlagsCache.storeBySetAction(sFolderFullNameRaw, sSubUid, iSetAction)
);
2015-03-06 08:42:40 +08:00
2021-08-13 15:58:43 +08:00
Remote.messageSetFlagged(()=>0, sFolderFullNameRaw, rootUids, true);
2015-03-06 08:42:40 +08:00
break;
2016-06-07 05:57:52 +08:00
case MessageSetAction.UnsetFlag:
rootUids.forEach(sSubUid =>
MessageFlagsCache.storeBySetAction(sFolderFullNameRaw, sSubUid, iSetAction)
);
2015-03-06 08:42:40 +08:00
2021-08-13 15:58:43 +08:00
Remote.messageSetFlagged(()=>0, sFolderFullNameRaw, rootUids, false);
2015-03-06 08:42:40 +08:00
break;
2016-06-30 08:02:45 +08:00
// no default
2014-08-20 23:03:12 +08:00
}
2014-08-22 23:08:56 +08:00
this.reloadFlagsCurrentMessageListAndMessageFromCache();
2014-08-20 23:03:12 +08:00
}
2015-11-19 01:32:29 +08:00
}
2014-08-20 23:03:12 +08:00
/**
2015-11-19 01:32:29 +08:00
* @param {string} query
2016-07-02 06:49:59 +08:00
* @param {Function} autocompleteCallback
2014-08-20 23:03:12 +08:00
*/
2016-07-02 06:49:59 +08:00
getAutocomplete(query, autocompleteCallback) {
Remote.suggestions((iError, data) => {
2021-03-18 21:48:21 +08:00
if (!iError && isArray(data.Result)) {
2019-07-05 03:19:24 +08:00
autocompleteCallback(
data.Result.map(item => (item && item[0] ? new EmailModel(item[0], item[1]) : null)).filter(v => v)
2019-07-05 03:19:24 +08:00
);
} else if (Notification.RequestAborted !== iError) {
2016-07-02 06:49:59 +08:00
autocompleteCallback([]);
2014-08-22 23:08:56 +08:00
}
2015-11-19 01:32:29 +08:00
}, query);
}
2014-08-20 23:03:12 +08:00
2014-08-22 23:08:56 +08:00
/**
* @param {string} sFullNameHash
* @param {boolean} bExpanded
*/
2015-11-19 01:32:29 +08:00
setExpandedFolder(sFullNameHash, bExpanded) {
2016-06-07 05:57:52 +08:00
let aExpandedList = Local.get(ClientSideKeyName.ExpandedFolders);
if (!isArray(aExpandedList)) {
2014-08-22 23:08:56 +08:00
aExpandedList = [];
}
2019-07-05 03:19:24 +08:00
if (bExpanded) {
if (!aExpandedList.includes(sFullNameHash))
aExpandedList.push(sFullNameHash);
2019-07-05 03:19:24 +08:00
} else {
aExpandedList = aExpandedList.filter(value => value !== sFullNameHash);
2014-08-22 23:08:56 +08:00
}
2016-06-07 05:57:52 +08:00
Local.set(ClientSideKeyName.ExpandedFolders, aExpandedList);
2015-11-19 01:32:29 +08:00
}
2021-11-05 17:20:06 +08:00
initLeftSideLayoutResizer() {
const left = elementById('rl-left'),
right = elementById('rl-right'),
fToggle = () =>
2021-11-05 17:20:06 +08:00
setLayoutResizer(left, right, ClientSideKeyName.FolderListSize,
(ThemeStore.isMobile() || leftPanelDisabled()) ? 0 : 'Width');
if (left && right) {
fToggle();
leftPanelDisabled.subscribe(fToggle);
}
2015-11-19 01:32:29 +08:00
}
2014-08-20 23:03:12 +08:00
2021-03-25 17:54:40 +08:00
/**
* @param {string} link
* @returns {boolean}
*/
download(link) {
if (ThemeStore.isMobile()) {
open(link, '_self');
focus();
} else {
const oLink = createElement('a');
oLink.href = link;
doc.body.appendChild(oLink).click();
oLink.remove();
}
return true;
}
2015-11-19 01:32:29 +08:00
logout() {
Remote.logout(() => rl.logoutReload());
2016-04-21 01:12:51 +08:00
}
2015-02-19 03:52:52 +08:00
2015-11-19 01:32:29 +08:00
bootstart() {
super.bootstart();
addEventListener('resize', () => leftPanelDisabled(ThemeStore.isMobile() || 1000 > innerWidth));
2021-08-31 22:21:40 +08:00
addEventListener('beforeunload', event => {
if (arePopupsVisible()) {
event.preventDefault();
return event.returnValue = "Are you sure you want to exit?";
}
}, {capture: true});
}
start() {
2021-03-10 18:44:48 +08:00
if (SettingsGet('Auth')) {
2021-04-13 01:15:33 +08:00
rl.setWindowTitle(i18n('GLOBAL/LOADING'));
2014-08-20 23:03:12 +08:00
2021-09-23 20:24:06 +08:00
NotificationUserStore.enableSoundNotification(!!SettingsGet('SoundNotification'));
NotificationUserStore.enableDesktopNotification(!!SettingsGet('DesktopNotifications'));
AccountUserStore.email(SettingsGet('Email'));
AccountUserStore.parentEmail(SettingsGet('ParentEmail'));
2021-04-13 01:15:33 +08:00
this.foldersReload(value => {
try {
if (value) {
2021-09-23 20:24:06 +08:00
value = pString(SettingsGet('StartupUrl'));
value && rl.route.setHash(root(value), true);
2021-04-13 01:15:33 +08:00
startScreens([
MailBoxUserScreen,
2021-09-23 17:05:19 +08:00
SettingsUserScreen
2021-04-13 01:15:33 +08:00
]);
setInterval(() => {
const cF = FolderUserStore.currentFolderFullNameRaw(),
iF = getFolderInboxName();
this.folderInformation(iF);
if (iF !== cF) {
this.folderInformation(cF);
}
this.folderInformationMultiply();
}, refreshFolders);
2014-10-29 06:05:50 +08:00
2021-04-13 01:15:33 +08:00
// Every 15 minutes
setInterval(()=>this.foldersReload(), 900000);
2014-10-29 06:05:50 +08:00
2021-09-23 20:24:06 +08:00
ContactUserStore.init();
2014-10-29 06:05:50 +08:00
2021-04-13 01:15:33 +08:00
this.accountsAndIdentities(true);
2015-02-19 03:52:52 +08:00
2021-04-13 01:15:33 +08:00
setTimeout(() => {
const cF = FolderUserStore.currentFolderFullNameRaw();
if (getFolderInboxName() !== cF) {
this.folderInformation(cF);
}
FolderUserStore.hasCapability('LIST-STATUS') || this.folderInformationMultiply(true);
2021-04-13 01:15:33 +08:00
}, 1000);
2021-08-13 15:58:43 +08:00
setTimeout(() => Remote.appDelayStart(()=>0), 35000);
2021-04-13 01:15:33 +08:00
// When auto-login is active
if (
2021-09-23 20:24:06 +08:00
SettingsGet('AccountSignMe') &&
navigator.registerProtocolHandler
2021-04-13 01:15:33 +08:00
) {
setTimeout(() => {
2021-04-13 01:15:33 +08:00
try {
navigator.registerProtocolHandler(
'mailto',
location.protocol + '//' + location.host + location.pathname + '?mailto&to=%s',
(SettingsGet('Title') || 'SnappyMail')
);
} catch (e) {} // eslint-disable-line no-empty
2021-09-23 20:24:06 +08:00
value = SettingsGet('MailToEmail');
value && mailToHelper(value);
2021-04-13 01:15:33 +08:00
}, 500);
}
2021-04-13 01:15:33 +08:00
['touchstart','mousedown','mousemove','keydown'].forEach(
t => doc.addEventListener(t, SettingsUserStore.delayLogout, {passive:true})
);
SettingsUserStore.delayLogout();
2021-03-18 23:12:24 +08:00
2021-11-05 17:20:06 +08:00
setTimeout(() => this.initLeftSideLayoutResizer(), 1);
2021-09-23 20:24:06 +08:00
setInterval(this.reloadTime(), 60000);
if (window.crypto && crypto.getRandomValues && Settings.capa(Capa.OpenPGP)) {
const script = createElement('script', {src:openPgpJs()});
script.onload = () => {
PgpUserStore.openpgp = openpgp;
if (window.Worker) {
try {
PgpUserStore.openpgp.initWorker({ path: openPgpWorkerJs() });
} catch (e) {
console.error(e);
}
}
PgpUserStore.openpgpKeyring = new openpgp.Keyring();
PgpUserStore.capaOpenPGP(true);
this.reloadOpenPgpKeys();
};
script.onerror = () => console.error(script.src);
doc.head.append(script);
}
2021-04-13 01:15:33 +08:00
} else {
this.logout();
}
2021-04-13 01:15:33 +08:00
} catch (e) {
console.error(e);
}
});
2019-07-05 03:19:24 +08:00
} else {
startScreens([LoginUserScreen]);
2014-08-20 23:03:12 +08:00
}
2021-07-19 20:26:32 +08:00
}
reloadTime()
{
setTimeout(() =>
2021-09-23 20:24:06 +08:00
doc.querySelectorAll('time').forEach(element => timeToNode(element))
2021-07-19 20:26:32 +08:00
, 1)
2015-11-19 01:32:29 +08:00
}
showMessageComposer(params = [])
{
showScreenPopup(ComposePopupView, params);
}
2015-11-19 01:32:29 +08:00
}
2015-11-19 01:32:29 +08:00
export default new AppUser();