Restructure JavaScript

Split list code from MessageUserStore into MessagelistUserStore
Move functions out of AppUser
This commit is contained in:
the-djmaze 2022-02-23 19:26:52 +01:00
parent 60b7f61e42
commit 661cd2aaf9
26 changed files with 1144 additions and 1186 deletions

View file

@ -1,17 +1,15 @@
import 'External/User/ko'; import 'External/User/ko';
import { isArray, arrayLength, pString, forEachObjectValue } from 'Common/Utils'; import { isArray, pString } from 'Common/Utils';
import { mailToHelper, setLayoutResizer } from 'Common/UtilsUser'; import { mailToHelper, setLayoutResizer } from 'Common/UtilsUser';
import { import {
Notification,
Scope Scope
} from 'Common/Enums'; } from 'Common/Enums';
import { import {
FolderType, FolderType,
SetSystemFoldersNotification, SetSystemFoldersNotification,
MessageSetAction,
ClientSideKeyName ClientSideKeyName
} from 'Common/EnumsUser'; } from 'Common/EnumsUser';
@ -34,9 +32,7 @@ import {
getFolderFromCacheList getFolderFromCacheList
} from 'Common/Cache'; } from 'Common/Cache';
import { mailBox } from 'Common/Links'; import { i18n, reloadTime } from 'Common/Translator';
import { getNotification, i18n } from 'Common/Translator';
import { SettingsUserStore } from 'Stores/User/Settings'; import { SettingsUserStore } from 'Stores/User/Settings';
import { NotificationUserStore } from 'Stores/User/Notification'; import { NotificationUserStore } from 'Stores/User/Notification';
@ -45,12 +41,11 @@ import { ContactUserStore } from 'Stores/User/Contact';
import { IdentityUserStore } from 'Stores/User/Identity'; import { IdentityUserStore } from 'Stores/User/Identity';
import { FolderUserStore } from 'Stores/User/Folder'; import { FolderUserStore } from 'Stores/User/Folder';
import { PgpUserStore } from 'Stores/User/Pgp'; import { PgpUserStore } from 'Stores/User/Pgp';
import { MessageUserStore } from 'Stores/User/Message'; import { MessagelistUserStore } from 'Stores/User/Messagelist';
import { ThemeStore } from 'Stores/Theme'; import { ThemeStore } from 'Stores/Theme';
import Remote from 'Remote/User/Fetch'; import Remote from 'Remote/User/Fetch';
import { EmailModel } from 'Model/Email';
import { AccountModel } from 'Model/Account'; import { AccountModel } from 'Model/Account';
import { IdentityModel } from 'Model/Identity'; import { IdentityModel } from 'Model/Identity';
@ -66,24 +61,16 @@ import { ComposePopupView } from 'View/Popup/Compose';
import { FolderSystemPopupView } from 'View/Popup/FolderSystem'; import { FolderSystemPopupView } from 'View/Popup/FolderSystem';
import { AskPopupView } from 'View/Popup/Ask'; import { AskPopupView } from 'View/Popup/Ask';
import { timeToNode } from 'Common/Momentor'; import { folderInformationMultiply, refreshFoldersInterval, messagesMoveHelper, messagesDeleteHelper } from 'Common/Folders';
import { loadFolders } from 'Model/FolderCollection';
// Every 5 minutes
const refreshFolders = 300000;
let moveCache = {};
class AppUser extends AbstractApp { class AppUser extends AbstractApp {
constructor() { constructor() {
super(Remote); super(Remote);
this.moveOrDeleteResponseHelper = this.moveOrDeleteResponseHelper.bind(this);
this.messagesMoveTrigger = this.messagesMoveTrigger.debounce(500);
// wakeUp // wakeUp
const interval = 3600000; // 60m const interval = 3600000; // 60m
var lastTime = Date.now(); let lastTime = Date.now();
setInterval(() => { setInterval(() => {
const currentTime = Date.now(); const currentTime = Date.now();
if (currentTime > (lastTime + interval + 1000)) { if (currentTime > (lastTime + interval + 1000)) {
@ -105,126 +92,6 @@ class AppUser extends AbstractApp {
(Settings.app('inIframe') ? parent : window).location.reload(); (Settings.app('inIframe') ? parent : window).location.reload();
} }
/**
* @param {boolean=} bDropPagePosition = false
* @param {boolean=} bDropCurrenFolderCache = false
*/
reloadMessageList(bDropPagePosition = false, bDropCurrenFolderCache = false) {
let iOffset = (MessageUserStore.listPage() - 1) * SettingsUserStore.messagesPerPage();
if (bDropCurrenFolderCache) {
setFolderHash(FolderUserStore.currentFolderFullName(), '');
}
if (bDropPagePosition) {
MessageUserStore.listPage(1);
MessageUserStore.listPageBeforeThread(1);
iOffset = 0;
rl.route.setHash(
mailBox(
FolderUserStore.currentFolderFullNameHash(),
MessageUserStore.listPage(),
MessageUserStore.listSearch(),
MessageUserStore.listThreadUid()
),
true,
true
);
}
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.currentFolderFullName(),
Offset: iOffset,
Limit: SettingsUserStore.messagesPerPage(),
Search: MessageUserStore.listSearch(),
ThreadUid: MessageUserStore.listThreadUid()
}
);
}
messagesMoveTrigger() {
const sTrashFolder = FolderUserStore.trashFolder(),
sSpamFolder = FolderUserStore.spamFolder();
forEachObjectValue(moveCache, item => {
const isSpam = sSpamFolder === item.To,
isTrash = sTrashFolder === item.To,
isHam = !isSpam && sSpamFolder === item.From && getFolderInboxName() === item.To;
Remote.request('MessageMove',
this.moveOrDeleteResponseHelper,
{
FromFolder: item.From,
ToFolder: item.To,
Uids: item.Uid.join(','),
MarkAsRead: (isSpam || isTrash) ? 1 : 0,
Learning: isSpam ? 'SPAM' : isHam ? 'HAM' : ''
},
null,
'',
['MessageList']
);
});
moveCache = {};
}
messagesMoveHelper(fromFolderFullName, toFolderFullName, uidsForMove) {
const hash = '$$' + fromFolderFullName + '$$' + toFolderFullName + '$$';
if (!moveCache[hash]) {
moveCache[hash] = {
From: fromFolderFullName,
To: toFolderFullName,
Uid: []
};
}
moveCache[hash].Uid = moveCache[hash].Uid.concat(uidsForMove).unique();
this.messagesMoveTrigger();
}
messagesDeleteHelper(sFromFolderFullName, aUidForRemove) {
Remote.request('MessageDelete',
this.moveOrDeleteResponseHelper,
{
Folder: sFromFolderFullName,
Uids: aUidForRemove.join(',')
},
null,
'',
['MessageList']
);
}
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(), '');
}
this.reloadMessageList(!MessageUserStore.list.length);
}
}
/** /**
* @param {number} iDeleteType * @param {number} iDeleteType
* @param {string} sFromFolderFullName * @param {string} sFromFolderFullName
@ -276,46 +143,16 @@ class AppUser extends AbstractApp {
showScreenPopup(AskPopupView, [ showScreenPopup(AskPopupView, [
i18n('POPUPS_ASK/DESC_WANT_DELETE_MESSAGES'), i18n('POPUPS_ASK/DESC_WANT_DELETE_MESSAGES'),
() => { () => {
this.messagesDeleteHelper(sFromFolderFullName, aUidForRemove); messagesDeleteHelper(sFromFolderFullName, aUidForRemove);
MessageUserStore.removeMessagesFromList(sFromFolderFullName, aUidForRemove); MessagelistUserStore.removeMessagesFromList(sFromFolderFullName, aUidForRemove);
} }
]); ]);
} else if (oMoveFolder) { } else if (oMoveFolder) {
this.messagesMoveHelper(sFromFolderFullName, oMoveFolder.fullName, aUidForRemove); messagesMoveHelper(sFromFolderFullName, oMoveFolder.fullName, aUidForRemove);
MessageUserStore.removeMessagesFromList(sFromFolderFullName, aUidForRemove, oMoveFolder.fullName); MessagelistUserStore.removeMessagesFromList(sFromFolderFullName, aUidForRemove, oMoveFolder.fullName);
} }
} }
/**
* @param {string} sFromFolderFullName
* @param {Array} aUidForMove
* @param {string} sToFolderFullName
* @param {boolean=} bCopy = false
*/
moveMessagesToFolder(sFromFolderFullName, aUidForMove, sToFolderFullName, bCopy) {
if (sFromFolderFullName !== sToFolderFullName && arrayLength(aUidForMove)) {
const oFromFolder = getFolderFromCacheList(sFromFolderFullName),
oToFolder = getFolderFromCacheList(sToFolderFullName);
if (oFromFolder && oToFolder) {
if (undefined === bCopy ? false : !!bCopy) {
Remote.request('MessageCopy', null, {
FromFolder: oFromFolder.fullName,
ToFolder: oToFolder.fullName,
Uids: aUidForMove.join(',')
});
} else {
this.messagesMoveHelper(oFromFolder.fullName, oToFolder.fullName, aUidForMove);
}
MessageUserStore.removeMessagesFromList(oFromFolder.fullName, aUidForMove, oToFolder.fullName, bCopy);
return true;
}
}
return false;
}
accountsAndIdentities() { accountsAndIdentities() {
AccountUserStore.loading(true); AccountUserStore.loading(true);
IdentityUserStore.loading(true); IdentityUserStore.loading(true);
@ -396,10 +233,10 @@ class AppUser extends AbstractApp {
MessageFlagsCache.setFor(folderFromCache.fullName, message.Uid.toString(), message.Flags) MessageFlagsCache.setFor(folderFromCache.fullName, message.Uid.toString(), message.Flags)
); );
MessageUserStore.reloadFlagsAndCachedMessage(); MessagelistUserStore.reloadFlagsAndCachedMessage();
} }
MessageUserStore.initUidNextAndNewMessages( MessagelistUserStore.initUidNextAndNewMessages(
folderFromCache.fullName, folderFromCache.fullName,
result.UidNext, result.UidNext,
result.NewMessages result.NewMessages
@ -407,7 +244,7 @@ class AppUser extends AbstractApp {
if (!hash || unreadCountChange || result.Hash !== hash) { if (!hash || unreadCountChange || result.Hash !== hash) {
if (folderFromCache.fullName === FolderUserStore.currentFolderFullName()) { if (folderFromCache.fullName === FolderUserStore.currentFolderFullName()) {
this.reloadMessageList(); MessagelistUserStore.reload();
} else if (getFolderInboxName() === folderFromCache.fullName) { } else if (getFolderInboxName() === folderFromCache.fullName) {
Remote.messageList(null, {Folder: getFolderInboxName()}, true); Remote.messageList(null, {Folder: getFolderInboxName()}, true);
} }
@ -421,126 +258,6 @@ class AppUser extends AbstractApp {
} }
} }
/**
* @param {boolean=} boot = false
*/
folderInformationMultiply(boot = false) {
const folders = FolderUserStore.getNextFolderNames(refreshFolders);
if (arrayLength(folders)) {
Remote.request('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) {
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.fullName);
}
if (!hash || item.Hash !== hash) {
if (folder.fullName === FolderUserStore.currentFolderFullName()) {
this.reloadMessageList();
}
} else if (unreadCountChange
&& folder.fullName === FolderUserStore.currentFolderFullName()
&& MessageUserStore.list.length) {
this.folderInformation(folder.fullName, MessageUserStore.list());
}
}
});
if (boot) {
setTimeout(() => this.folderInformationMultiply(true), 2000);
}
}
}, {
Folders: folders
});
}
}
/**
* @param {string} sFolderFullName
* @param {number} iSetAction
* @param {Array=} messages = null
*/
messageListAction(sFolderFullName, iSetAction, messages) {
messages = messages || MessageUserStore.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);
}
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)
);
Remote.request('MessageSetFlagged', null, {
Folder: sFolderFullName,
Uids: rootUids.join(','),
SetAction: iSetAction == MessageSetAction.SetFlag ? 1 : 0
});
break;
// no default
}
MessageUserStore.reloadFlagsAndCachedMessage();
}
}
/**
* @param {string} query
* @param {Function} autocompleteCallback
*/
getAutocomplete(query, autocompleteCallback) {
Remote.suggestions((iError, data) => {
if (!iError && isArray(data.Result)) {
autocompleteCallback(
data.Result.map(item => (item && item[0] ? new EmailModel(item[0], item[1]) : null)).filter(v => v)
);
} else if (Notification.RequestAborted !== iError) {
autocompleteCallback([]);
}
}, query);
}
logout() { logout() {
Remote.request('Logout', () => rl.logoutReload()); Remote.request('Logout', () => rl.logoutReload());
} }
@ -569,7 +286,7 @@ class AppUser extends AbstractApp {
SettingsUserStore.init(); SettingsUserStore.init();
ContactUserStore.init(); ContactUserStore.init();
Remote.foldersReload(value => { loadFolders(value => {
try { try {
if (value) { if (value) {
startScreens([ startScreens([
@ -584,8 +301,8 @@ class AppUser extends AbstractApp {
if (iF !== cF) { if (iF !== cF) {
this.folderInformation(cF); this.folderInformation(cF);
} }
this.folderInformationMultiply(); folderInformationMultiply();
}, refreshFolders); }, refreshFoldersInterval);
ContactUserStore.init(); ContactUserStore.init();
@ -596,7 +313,7 @@ class AppUser extends AbstractApp {
if (getFolderInboxName() !== cF) { if (getFolderInboxName() !== cF) {
this.folderInformation(cF); this.folderInformation(cF);
} }
FolderUserStore.hasCapability('LIST-STATUS') || this.folderInformationMultiply(true); FolderUserStore.hasCapability('LIST-STATUS') || folderInformationMultiply(true);
}, 1000); }, 1000);
setTimeout(() => Remote.request('AppDelayStart'), 35000); setTimeout(() => Remote.request('AppDelayStart'), 35000);
@ -639,7 +356,7 @@ class AppUser extends AbstractApp {
} }
}, 1); }, 1);
setInterval(this.reloadTime(), 60000); setInterval(reloadTime(), 60000);
PgpUserStore.init(); PgpUserStore.init();
} else { } else {
@ -655,13 +372,6 @@ class AppUser extends AbstractApp {
} }
} }
reloadTime()
{
setTimeout(() =>
doc.querySelectorAll('time').forEach(element => timeToNode(element))
, 1)
}
showMessageComposer(params = []) showMessageComposer(params = [])
{ {
showScreenPopup(ComposePopupView, params); showScreenPopup(ComposePopupView, params);

221
dev/Common/Folders.js Normal file
View file

@ -0,0 +1,221 @@
import { isArray, arrayLength } from 'Common/Utils';
import {
MessageFlagsCache,
setFolderHash,
getFolderHash,
getFolderInboxName,
getFolderFromCacheList
} 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';
import Remote from 'Remote/User/Fetch';
export const
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=} fDisableCallback
* @param {Function=} fRenameCallback
* @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))
});
}
if (oItem.subFolders.length) {
foldersWalk(oItem.subFolders());
}
});
};
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;
},
// Every 5 minutes
refreshFoldersInterval = 300000,
/**
* @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 => {
const hash = getFolderHash(item.Folder),
folder = getFolderFromCacheList(item.Folder);
if (folder) {
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.fullName);
}
if (!hash || item.Hash !== hash) {
if (folder.fullName === FolderUserStore.currentFolderFullName()) {
MessagelistUserStore.reload();
}
} else if (unreadCountChange
&& folder.fullName === FolderUserStore.currentFolderFullName()
&& MessagelistUserStore.length) {
rl.app.folderInformation(folder.fullName, MessagelistUserStore());
}
}
});
if (boot) {
setTimeout(() => folderInformationMultiply(true), 2000);
}
}
}, {
Folders: folders
});
}
},
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;
Remote.request('MessageMove',
moveOrDeleteResponseHelper,
{
FromFolder: fromFolderFullName,
ToFolder: toFolderFullName,
Uids: uidsForMove.join(','),
MarkAsRead: (isSpam || FolderUserStore.trashFolder() === toFolderFullName) ? 1 : 0,
Learning: isSpam ? 'SPAM' : isHam ? 'HAM' : ''
},
null,
'',
['MessageList']
);
},
messagesDeleteHelper = (sFromFolderFullName, aUidForRemove) => {
Remote.request('MessageDelete',
moveOrDeleteResponseHelper,
{
Folder: sFromFolderFullName,
Uids: aUidForRemove.join(',')
},
null,
'',
['MessageList']
);
},
/**
* @param {string} sFromFolderFullName
* @param {Array} aUidForMove
* @param {string} sToFolderFullName
* @param {boolean=} bCopy = false
*/
moveMessagesToFolder = (sFromFolderFullName, aUidForMove, sToFolderFullName, bCopy) => {
if (sFromFolderFullName !== sToFolderFullName && arrayLength(aUidForMove)) {
const oFromFolder = getFolderFromCacheList(sFromFolderFullName),
oToFolder = getFolderFromCacheList(sToFolderFullName);
if (oFromFolder && oToFolder) {
if (bCopy) {
Remote.request('MessageCopy', null, {
FromFolder: oFromFolder.fullName,
ToFolder: oToFolder.fullName,
Uids: aUidForMove.join(',')
});
} else {
messagesMoveHelper(oFromFolder.fullName, oToFolder.fullName, aUidForMove);
}
MessagelistUserStore.removeMessagesFromList(oFromFolder.fullName, aUidForMove, oToFolder.fullName, bCopy);
return true;
}
}
return false;
};

View file

@ -1,55 +0,0 @@
import { i18n } from 'Common/Translator';
export function timestampToString(timeStampInUTC, formatStr) {
const now = Date.now(),
time = 0 < timeStampInUTC ? Math.min(now, timeStampInUTC * 1000) : (0 === timeStampInUTC ? now : 0);
if (31536000000 < time) {
const m = new Date(time);
switch (formatStr) {
case 'FROMNOW':
return m.fromNow();
case 'SHORT': {
if (4 >= (now - time) / 3600000)
return m.fromNow();
const mt = m.getTime(), date = new Date,
dt = date.setHours(0,0,0,0);
if (mt > dt)
return i18n('MESSAGE_LIST/TODAY_AT', {TIME: m.format('LT')});
if (mt > dt - 86400000)
return i18n('MESSAGE_LIST/YESTERDAY_AT', {TIME: m.format('LT')});
if (date.getFullYear() === m.getFullYear())
return m.format('d M');
return m.format('LL');
}
case 'FULL':
return m.format('LLL');
default:
return m.format(formatStr);
}
}
return '';
}
export function timeToNode(element, time) {
try {
if (time) {
element.dateTime = (new Date(time * 1000)).format('Y-m-d\\TH:i:s');
} else {
time = Date.parse(element.dateTime) / 1000;
}
let key = element.dataset.momentFormat;
if (key) {
element.textContent = timestampToString(time, key);
}
if ((key = element.dataset.momentFormatTitle)) {
element.title = timestampToString(time, key);
}
} catch (e) {
// prevent knockout crashes
console.error(e);
}
}

View file

@ -82,6 +82,64 @@ export const
element.querySelectorAll('[data-i18n]').forEach(item => i18nToNode(item)) element.querySelectorAll('[data-i18n]').forEach(item => i18nToNode(item))
, 1), , 1),
timestampToString = (timeStampInUTC, formatStr) => {
const now = Date.now(),
time = 0 < timeStampInUTC ? Math.min(now, timeStampInUTC * 1000) : (0 === timeStampInUTC ? now : 0);
if (31536000000 < time) {
const m = new Date(time);
switch (formatStr) {
case 'FROMNOW':
return m.fromNow();
case 'SHORT': {
if (4 >= (now - time) / 3600000)
return m.fromNow();
const mt = m.getTime(), date = new Date,
dt = date.setHours(0,0,0,0);
if (mt > dt)
return i18n('MESSAGE_LIST/TODAY_AT', {TIME: m.format('LT')});
if (mt > dt - 86400000)
return i18n('MESSAGE_LIST/YESTERDAY_AT', {TIME: m.format('LT')});
if (date.getFullYear() === m.getFullYear())
return m.format('d M');
return m.format('LL');
}
case 'FULL':
return m.format('LLL');
default:
return m.format(formatStr);
}
}
return '';
},
timeToNode = (element, time) => {
try {
if (time) {
element.dateTime = (new Date(time * 1000)).format('Y-m-d\\TH:i:s');
} else {
time = Date.parse(element.dateTime) / 1000;
}
let key = element.dataset.momentFormat;
if (key) {
element.textContent = timestampToString(time, key);
}
if ((key = element.dataset.momentFormatTitle)) {
element.title = timestampToString(time, key);
}
} catch (e) {
// prevent knockout crashes
console.error(e);
}
},
reloadTime = () => setTimeout(() =>
doc.querySelectorAll('time').forEach(element => timeToNode(element))
, 1),
/** /**
* @param {Function} startCallback * @param {Function} startCallback
* @param {Function=} langCallback = null * @param {Function=} langCallback = null
@ -129,7 +187,7 @@ export const
// reload the data // reload the data
if (init()) { if (init()) {
i18nToNodes(doc); i18nToNodes(doc);
admin || rl.app.reloadTime(); admin || reloadTime();
trigger(!trigger()); trigger(!trigger());
} }
script.remove(); script.remove();

View file

@ -1,26 +1,18 @@
import { ComposeType/*, FolderType*/ } from 'Common/EnumsUser'; import { MessageFlagsCache, addRequestedMessage } from 'Common/Cache';
import { MessageSetAction, ComposeType/*, FolderType*/ } from 'Common/EnumsUser';
import { doc, createElement, elementById } from 'Common/Globals';
import { plainToHtml } from 'Common/Html';
import { getNotification } from 'Common/Translator';
import { EmailModel } from 'Model/Email'; import { EmailModel } from 'Model/Email';
import { isArray } from 'Common/Utils'; import { MessageModel } from 'Model/Message';
import { doc, createElement } from 'Common/Globals'; import { MessageUserStore } from 'Stores/User/Message';
import { FolderUserStore } from 'Stores/User/Folder'; import { MessagelistUserStore } from 'Stores/User/Messagelist';
import { SettingsUserStore } from 'Stores/User/Settings'; import { SettingsUserStore } from 'Stores/User/Settings';
import * as Local from 'Storage/Client'; import * as Local from 'Storage/Client';
import { plainToHtml } from 'Common/Html';
import { ThemeStore } from 'Stores/Theme'; import { ThemeStore } from 'Stores/Theme';
export const export const
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 {string} link * @param {string} link
* @returns {boolean} * @returns {boolean}
@ -39,69 +31,6 @@ download = (link, name = "") => {
} }
}, },
/**
* @param {Array=} aDisabled
* @param {Array=} aHeaderLines
* @param {Function=} fDisableCallback
* @param {Function=} fRenameCallback
* @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))
});
}
if (oItem.subFolders.length) {
foldersWalk(oItem.subFolders());
}
});
};
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;
},
/** /**
* @returns {function} * @returns {function}
*/ */
@ -334,4 +263,123 @@ setLayoutResizer = (source, target, sClientSideKeyName, mode) =>
} else { } else {
source.observer && source.observer.disconnect(); source.observer && source.observer.disconnect();
} }
},
populateMessageBody = (oMessage, preload) => {
if (oMessage) {
preload || MessageUserStore.hideMessageBodies();
preload || MessageUserStore.loading(true);
rl.app.Remote.message((iError, oData/*, bCached*/) => {
if (iError) {
if (Notification.RequestAborted !== iError && !preload) {
MessageUserStore.message(null);
MessageUserStore.error(getNotification(iError));
}
} else {
oMessage = preload ? oMessage : null;
let
isNew = false,
json = oData && oData.Result,
message = oMessage || MessageUserStore.message();
if (
json &&
MessageModel.validJson(json) &&
message &&
message.folder === json.Folder
) {
const threads = message.threads(),
messagesDom = MessageUserStore.bodiesDom();
if (!oMessage && message.uid != json.Uid && threads.includes(json.Uid)) {
message = MessageModel.reviveFromJson(json);
if (message) {
message.threads(threads);
MessageFlagsCache.initMessage(message);
// Set clone
MessageUserStore.message(MessageModel.fromMessageListItem(message));
message = MessageUserStore.message();
isNew = true;
}
}
if (message && message.uid == json.Uid) {
oMessage || MessageUserStore.error('');
/*
if (bCached) {
delete json.Flags;
}
*/
isNew || message.revivePropertiesFromJson(json);
addRequestedMessage(message.folder, message.uid);
if (messagesDom) {
let id = 'rl-msg-' + message.hash.replace(/[^a-zA-Z0-9]/g, ''),
body = elementById(id);
if (body) {
message.body = body;
message.isHtml(body.classList.contains('html'));
message.hasImages(body.rlHasImages);
} else {
body = Element.fromHTML('<div id="' + id + '" hidden="" class="b-text-part '
+ (message.pgpSigned() ? ' openpgp-signed' : '')
+ (message.pgpEncrypted() ? ' openpgp-encrypted' : '')
+ '">'
+ '</div>');
message.body = body;
if (!SettingsUserStore.viewHTML() || !message.viewHtml()) {
message.viewPlain();
}
MessageUserStore.purgeMessageBodyCache();
}
messagesDom.append(body);
if (!oMessage) {
MessageUserStore.activeDom(message.body);
MessageUserStore.hideMessageBodies();
message.body.hidden = false;
}
oMessage && message.viewPopupMessage();
}
MessageFlagsCache.initMessage(message);
if (message.isUnseen()) {
MessageUserStore.MessageSeenTimer = setTimeout(
() => MessagelistUserStore.setAction(message.folder, MessageSetAction.SetSeen, [message]),
SettingsUserStore.messageReadDelay() * 1000 // seconds
);
}
if (message && isNew) {
let selectedMessage = MessagelistUserStore.selectedMessage();
if (
selectedMessage &&
(message.folder !== selectedMessage.folder || message.uid != selectedMessage.uid)
) {
MessagelistUserStore.selectedMessage(null);
if (1 === MessagelistUserStore.length) {
MessagelistUserStore.focusedMessage(null);
}
} else if (!selectedMessage) {
selectedMessage = MessagelistUserStore.find(
subMessage =>
subMessage &&
subMessage.folder === message.folder &&
subMessage.uid == message.uid
);
if (selectedMessage) {
MessagelistUserStore.selectedMessage(selectedMessage);
MessagelistUserStore.focusedMessage(selectedMessage);
}
}
}
}
}
}
preload || MessageUserStore.loading(false);
}, oMessage.folder, oMessage.uid);
}
}; };

View file

@ -1,11 +1,12 @@
import 'External/ko'; import 'External/ko';
import ko from 'ko'; import ko from 'ko';
import { HtmlEditor } from 'Common/Html'; import { HtmlEditor } from 'Common/Html';
import { timeToNode } from 'Common/Momentor'; import { timeToNode } from 'Common/Translator';
import { elementById } from 'Common/Globals'; import { elementById } from 'Common/Globals';
import { isArray } from 'Common/Utils'; import { isArray } from 'Common/Utils';
import { EmailAddressesComponent } from 'Component/EmailAddresses'; import { EmailAddressesComponent } from 'Component/EmailAddresses';
import { ThemeStore } from 'Stores/Theme'; import { ThemeStore } from 'Stores/Theme';
import { moveMessagesToFolder } from 'Common/Folders';
const rlContentType = 'snappymail/action', const rlContentType = 'snappymail/action',
@ -145,7 +146,7 @@ ko.bindingHandlers.dropmessages = {
if ('messages' === getDragAction(e) && ['move','copy'].includes(e.dataTransfer.effectAllowed)) { if ('messages' === getDragAction(e) && ['move','copy'].includes(e.dataTransfer.effectAllowed)) {
let data = dragData.data; let data = dragData.data;
if (folder && data && data.folder && isArray(data.uids)) { if (folder && data && data.folder && isArray(data.uids)) {
rl.app.moveMessagesToFolder(data.folder, data.uids, folder.fullName, data.copy && e.ctrlKey); moveMessagesToFolder(data.folder, data.uids, folder.fullName, data.copy && e.ctrlKey);
} }
} }
}); });

1
dev/External/ko.js vendored
View file

@ -1,3 +1,4 @@
import ko from 'ko';
import { i18nToNodes } from 'Common/Translator'; import { i18nToNodes } from 'Common/Translator';
import { doc, createElement } from 'Common/Globals'; import { doc, createElement } from 'Common/Globals';
import { SaveSettingsStep } from 'Common/Enums'; import { SaveSettingsStep } from 'Common/Enums';

View file

@ -10,12 +10,12 @@ import * as Local from 'Storage/Client';
import { AppUserStore } from 'Stores/User/App'; import { AppUserStore } from 'Stores/User/App';
import { FolderUserStore } from 'Stores/User/Folder'; import { FolderUserStore } from 'Stores/User/Folder';
import { MessageUserStore } from 'Stores/User/Message'; import { MessagelistUserStore } from 'Stores/User/Messagelist';
import { SettingsUserStore } from 'Stores/User/Settings'; import { SettingsUserStore } from 'Stores/User/Settings';
import ko from 'ko'; import ko from 'ko';
import { sortFolders } from 'Common/UtilsUser'; import { sortFolders } from 'Common/Folders';
import { i18n, trigger as translatorTrigger } from 'Common/Translator'; import { i18n, trigger as translatorTrigger } from 'Common/Translator';
import { AbstractModel } from 'Knoin/AbstractModel'; import { AbstractModel } from 'Knoin/AbstractModel';
@ -24,6 +24,8 @@ import { koComputable } from 'External/ko';
//import { mailBox } from 'Common/Links'; //import { mailBox } from 'Common/Links';
import Remote from 'Remote/User/Fetch';
const const
isPosNumeric = value => null != value && /^[0-9]*$/.test(value.toString()), isPosNumeric = value => null != value && /^[0-9]*$/.test(value.toString()),
@ -40,6 +42,51 @@ const
Spam: 0, Spam: 0,
Trash: 0, Trash: 0,
Archive: 0 Archive: 0
},
kolabTypes = {
configuration: 'CONFIGURATION',
event: 'CALENDAR',
contact: 'CONTACTS',
task: 'TASKS',
note: 'NOTES',
file: 'FILES',
journal: 'JOURNAL'
},
getKolabFolderName = type => kolabTypes[type] ? 'Kolab ' + i18n('SETTINGS_FOLDERS/TYPE_' + kolabTypes[type]) : '',
getSystemFolderName = (type, def) => {
switch (type) {
case FolderType.Inbox:
case FolderType.Sent:
case FolderType.Drafts:
case FolderType.Trash:
case FolderType.Archive:
return i18n('FOLDER_LIST/' + getKeyByValue(FolderType, type).toUpperCase() + '_NAME');
case FolderType.Spam:
return i18n('GLOBAL/SPAM');
// no default
}
return def;
};
export const
/**
* @param {?Function} fCallback
*/
loadFolders = fCallback => {
// clearTimeout(this.foldersTimeout);
Remote.abort('Folders')
.post('Folders', FolderUserStore.foldersLoading)
.then(data => {
data = FolderCollectionModel.reviveFromJson(data.Result);
data && data.storeIt();
fCallback && fCallback(true);
// Repeat every 15 minutes?
// this.foldersTimeout = setTimeout(loadFolders, 900000);
})
.catch(() => fCallback && setTimeout(fCallback, 1, false));
}; };
export class FolderCollectionModel extends AbstractCollectionModel export class FolderCollectionModel extends AbstractCollectionModel
@ -163,36 +210,6 @@ export class FolderCollectionModel extends AbstractCollectionModel
} }
function getKolabFolderName(type)
{
const types = {
configuration: 'CONFIGURATION',
event: 'CALENDAR',
contact: 'CONTACTS',
task: 'TASKS',
note: 'NOTES',
file: 'FILES',
journal: 'JOURNAL'
};
return types[type] ? 'Kolab ' + i18n('SETTINGS_FOLDERS/TYPE_' + types[type]) : '';
}
function getSystemFolderName(type, def)
{
switch (type) {
case FolderType.Inbox:
case FolderType.Sent:
case FolderType.Drafts:
case FolderType.Trash:
case FolderType.Archive:
return i18n('FOLDER_LIST/' + getKeyByValue(FolderType, type).toUpperCase() + '_NAME');
case FolderType.Spam:
return i18n('GLOBAL/SPAM');
// no default
}
return def;
}
export class FolderModel extends AbstractModel { export class FolderModel extends AbstractModel {
constructor() { constructor() {
super(); super();
@ -296,7 +313,7 @@ export class FolderModel extends AbstractModel {
isInbox: () => FolderType.Inbox === folder.type(), isInbox: () => FolderType.Inbox === folder.type(),
isFlagged: () => FolderUserStore.currentFolder() === folder isFlagged: () => FolderUserStore.currentFolder() === folder
&& MessageUserStore.listSearch().includes('flagged'), && MessagelistUserStore.listSearch().includes('flagged'),
hasVisibleSubfolders: () => !!folder.subFolders().find(folder => folder.visible()), hasVisibleSubfolders: () => !!folder.subFolders().find(folder => folder.visible()),

View file

@ -532,52 +532,52 @@ export class MessageModel extends AbstractModel {
* @param {MessageModel} message * @param {MessageModel} message
* @returns {MessageModel} * @returns {MessageModel}
*/ */
populateByMessageListItem(message) { static fromMessageListItem(message) {
this.clear(); let self = new MessageModel();
if (message) { if (message) {
this.folder = message.folder; self.folder = message.folder;
this.uid = message.uid; self.uid = message.uid;
this.hash = message.hash; self.hash = message.hash;
this.requestHash = message.requestHash; self.requestHash = message.requestHash;
this.subject(message.subject()); self.subject(message.subject());
this.plain(message.plain()); self.plain(message.plain());
this.html(message.html()); self.html(message.html());
this.size(message.size()); self.size(message.size());
this.spamScore(message.spamScore()); self.spamScore(message.spamScore());
this.spamResult(message.spamResult()); self.spamResult(message.spamResult());
this.isSpam(message.isSpam()); self.isSpam(message.isSpam());
this.hasVirus(message.hasVirus()); self.hasVirus(message.hasVirus());
this.dateTimeStampInUTC(message.dateTimeStampInUTC()); self.dateTimeStampInUTC(message.dateTimeStampInUTC());
this.priority(message.priority()); self.priority(message.priority());
this.hasExternals(message.hasExternals()); self.hasExternals(message.hasExternals());
this.emails = message.emails; self.emails = message.emails;
this.from = message.from; self.from = message.from;
this.to = message.to; self.to = message.to;
this.cc = message.cc; self.cc = message.cc;
this.bcc = message.bcc; self.bcc = message.bcc;
this.replyTo = message.replyTo; self.replyTo = message.replyTo;
this.deliveredTo = message.deliveredTo; self.deliveredTo = message.deliveredTo;
this.unsubsribeLinks(message.unsubsribeLinks); self.unsubsribeLinks(message.unsubsribeLinks);
this.flags(message.flags()); self.flags(message.flags());
this.priority(message.priority()); self.priority(message.priority());
this.selected(message.selected()); self.selected(message.selected());
this.checked(message.checked()); self.checked(message.checked());
this.attachments(message.attachments()); self.attachments(message.attachments());
this.threads(message.threads()); self.threads(message.threads());
} }
this.computeSenderEmail(); self.computeSenderEmail();
return this; return self;
} }
showExternalImages() { showExternalImages() {

View file

@ -16,9 +16,7 @@ import { FolderUserStore } from 'Stores/User/Folder';
import { AbstractFetchRemote } from 'Remote/AbstractFetch'; import { AbstractFetchRemote } from 'Remote/AbstractFetch';
import { FolderCollectionModel } from 'Model/FolderCollection'; import { MessagelistUserStore } from 'Stores/User/Messagelist';
import { MessageUserStore } from 'Stores/User/Message';
class RemoteUserFetch extends AbstractFetchRemote { class RemoteUserFetch extends AbstractFetchRemote {
@ -132,7 +130,7 @@ class RemoteUserFetch extends AbstractFetchRemote {
UidNext: getFolderUidNext(folder) // Used to check for new messages UidNext: getFolderUidNext(folder) // Used to check for new messages
}); });
} else if (SettingsUserStore.useThreads()) { } else if (SettingsUserStore.useThreads()) {
MessageUserStore.reloadFlagsAndCachedMessage(); MessagelistUserStore.reloadFlagsAndCachedMessage();
} }
} }
@ -200,23 +198,6 @@ class RemoteUserFetch extends AbstractFetchRemote {
); );
} }
/**
* @param {?Function} fCallback
*/
foldersReload(fCallback) {
// clearTimeout(this.foldersTimeout);
this.abort('Folders')
.post('Folders', FolderUserStore.foldersLoading)
.then(data => {
data = FolderCollectionModel.reviveFromJson(data.Result);
data && data.storeIt();
fCallback && fCallback(true);
// Repeat every 15 minutes?
// this.foldersTimeout = setTimeout(() => this.foldersReload(), 900000);
})
.catch(() => fCallback && setTimeout(fCallback, 1, false));
}
/* /*
folderMove(sPrevFolderFullName, sNewFolderFullName, bSubscribe) { folderMove(sPrevFolderFullName, sNewFolderFullName, bSubscribe) {
return this.post('FolderMove', FolderUserStore.foldersRenaming, { return this.post('FolderMove', FolderUserStore.foldersRenaming, {

View file

@ -10,7 +10,7 @@ import { SettingsUserStore } from 'Stores/User/Settings';
import { AppUserStore } from 'Stores/User/App'; import { AppUserStore } from 'Stores/User/App';
import { AccountUserStore } from 'Stores/User/Account'; import { AccountUserStore } from 'Stores/User/Account';
import { FolderUserStore } from 'Stores/User/Folder'; import { FolderUserStore } from 'Stores/User/Folder';
import { MessageUserStore } from 'Stores/User/Message'; import { MessagelistUserStore } from 'Stores/User/Messagelist';
import { ThemeStore } from 'Stores/Theme'; import { ThemeStore } from 'Stores/Theme';
import { SystemDropDownUserView } from 'View/User/SystemDropDown'; import { SystemDropDownUserView } from 'View/User/SystemDropDown';
@ -70,11 +70,11 @@ export class MailBoxUserScreen extends AbstractScreen {
FolderUserStore.currentFolder(folder); FolderUserStore.currentFolder(folder);
MessageUserStore.listPage(1 > page ? 1 : page); MessagelistUserStore.page(1 > page ? 1 : page);
MessageUserStore.listSearch(search); MessagelistUserStore.listSearch(search);
MessageUserStore.listThreadUid((folderHash === threadUid) ? 0 : pInt(threadUid)); MessagelistUserStore.threadUid((folderHash === threadUid) ? 0 : pInt(threadUid));
rl.app.reloadMessageList(); MessagelistUserStore.reload();
} }
} }

View file

@ -9,7 +9,7 @@ import { getNotification } from 'Common/Translator';
import { setFolder, getFolderFromCacheList, removeFolderFromCacheList } from 'Common/Cache'; import { setFolder, getFolderFromCacheList, removeFolderFromCacheList } from 'Common/Cache';
import { Capa } from 'Common/Enums'; import { Capa } from 'Common/Enums';
import { defaultOptionsAfterRender } from 'Common/Utils'; import { defaultOptionsAfterRender } from 'Common/Utils';
import { sortFolders } from 'Common/UtilsUser'; import { sortFolders } from 'Common/Folders';
import { initOnStartOrLangChange, i18n } from 'Common/Translator'; import { initOnStartOrLangChange, i18n } from 'Common/Translator';
import { FolderUserStore } from 'Stores/User/Folder'; import { FolderUserStore } from 'Stores/User/Folder';
@ -21,6 +21,7 @@ import { showScreenPopup } from 'Knoin/Knoin';
import { FolderCreatePopupView } from 'View/Popup/FolderCreate'; import { FolderCreatePopupView } from 'View/Popup/FolderCreate';
import { FolderSystemPopupView } from 'View/Popup/FolderSystem'; import { FolderSystemPopupView } from 'View/Popup/FolderSystem';
import { loadFolders } from 'Model/FolderCollection';
const folderForDeletion = ko.observable(null).askDeleteHelper(); const folderForDeletion = ko.observable(null).askDeleteHelper();
@ -79,8 +80,8 @@ export class FoldersUserSettings /*extends AbstractViewSettings*/ {
if (folder.subFolders.length) { if (folder.subFolders.length) {
Remote.setTrigger(FolderUserStore.foldersLoading, true); Remote.setTrigger(FolderUserStore.foldersLoading, true);
// clearTimeout(Remote.foldersTimeout); // clearTimeout(Remote.foldersTimeout);
// Remote.foldersTimeout = setTimeout(() => Remote.foldersReload(), 500); // Remote.foldersTimeout = setTimeout(loadFolders, 500);
setTimeout(() => Remote.foldersReload(), 500); setTimeout(loadFolders, 500);
// TODO: rename all subfolders with folder.delimiter to prevent reload? // TODO: rename all subfolders with folder.delimiter to prevent reload?
} else { } else {
removeFolderFromCacheList(folder.fullName); removeFolderFromCacheList(folder.fullName);

View file

@ -15,6 +15,7 @@ import { SettingsUserStore } from 'Stores/User/Settings';
import { IdentityUserStore } from 'Stores/User/Identity'; import { IdentityUserStore } from 'Stores/User/Identity';
import { NotificationUserStore } from 'Stores/User/Notification'; import { NotificationUserStore } from 'Stores/User/Notification';
import { MessageUserStore } from 'Stores/User/Message'; import { MessageUserStore } from 'Stores/User/Message';
import { MessagelistUserStore } from 'Stores/User/Messagelist';
import Remote from 'Remote/User/Fetch'; import Remote from 'Remote/User/Fetch';
@ -117,7 +118,7 @@ export class GeneralUserSettings /*extends AbstractViewSettings*/ {
showImages: value => Remote.saveSetting('ShowImages', value ? 1 : 0), showImages: value => Remote.saveSetting('ShowImages', value ? 1 : 0),
removeColors: value => { removeColors: value => {
let dom = MessageUserStore.messagesBodiesDom(); let dom = MessageUserStore.bodiesDom();
if (dom) { if (dom) {
dom.innerHTML = ''; dom.innerHTML = '';
} }
@ -137,12 +138,12 @@ export class GeneralUserSettings /*extends AbstractViewSettings*/ {
replySameFolder: value => Remote.saveSetting('ReplySameFolder', value ? 1 : 0), replySameFolder: value => Remote.saveSetting('ReplySameFolder', value ? 1 : 0),
useThreads: value => { useThreads: value => {
MessageUserStore.list([]); MessagelistUserStore([]);
Remote.saveSetting('UseThreads', value ? 1 : 0); Remote.saveSetting('UseThreads', value ? 1 : 0);
}, },
layout: value => { layout: value => {
MessageUserStore.list([]); MessagelistUserStore([]);
Remote.saveSetting('Layout', value, settingsSaveHelperSimpleFunction(this.layoutTrigger, this)); Remote.saveSetting('Layout', value, settingsSaveHelperSimpleFunction(this.layoutTrigger, this));
} }
}); });

View file

@ -7,7 +7,7 @@ import { forEachObjectEntry } from 'Common/Utils';
import { addObservablesTo, addSubscribablesTo, addComputablesTo } from 'External/ko'; import { addObservablesTo, addSubscribablesTo, addComputablesTo } from 'External/ko';
import { getFolderInboxName, getFolderFromCacheList } from 'Common/Cache'; import { getFolderInboxName, getFolderFromCacheList } from 'Common/Cache';
import { Settings } from 'Common/Globals'; import { Settings } from 'Common/Globals';
//import Remote from 'Remote/User/Fetch'; Circular dependency //import Remote from 'Remote/User/Fetch'; // Circular dependency
export const FolderUserStore = new class { export const FolderUserStore = new class {
constructor() { constructor() {

View file

@ -1,137 +1,30 @@
import ko from 'ko'; import { Scope } from 'Common/Enums';
import { koComputable } from 'External/ko'; import { elementById } from 'Common/Globals';
import { addObservablesTo, addSubscribablesTo } from 'External/ko';
import { Scope, Notification } from 'Common/Enums';
import { MessageSetAction } from 'Common/EnumsUser';
import { $htmlCL, elementById } from 'Common/Globals';
import { arrayLength, pInt, pString } from 'Common/Utils';
import { addObservablesTo, addComputablesTo, addSubscribablesTo } from 'External/ko';
import {
getFolderInboxName,
addNewMessageCache,
setFolderUidNext,
getFolderFromCacheList,
setFolderHash,
MessageFlagsCache,
addRequestedMessage,
clearNewMessageCache
} from 'Common/Cache';
import { mailBox } from 'Common/Links';
import { i18n, getNotification } from 'Common/Translator';
import { EmailCollectionModel } from 'Model/EmailCollection';
import { MessageModel } from 'Model/Message';
import { MessageCollectionModel } from 'Model/MessageCollection';
import { AppUserStore } from 'Stores/User/App'; import { AppUserStore } from 'Stores/User/App';
import { AccountUserStore } from 'Stores/User/Account';
import { FolderUserStore } from 'Stores/User/Folder';
import { SettingsUserStore } from 'Stores/User/Settings'; import { SettingsUserStore } from 'Stores/User/Settings';
import { NotificationUserStore } from 'Stores/User/Notification';
//import Remote from 'Remote/User/Fetch'; Circular dependency
const
isChecked = item => item.checked();
let MessageSeenTimer;
export const MessageUserStore = new class { export const MessageUserStore = new class {
constructor() { constructor() {
this.staticMessage = new MessageModel();
this.list = ko.observableArray().extend({ debounce: 0 });
addObservablesTo(this, { addObservablesTo(this, {
listCount: 0,
listSearch: '',
listThreadUid: 0,
listPage: 1,
listPageBeforeThread: 1,
listError: '',
listEndHash: '',
listEndThreadUid: 0,
listLoading: false,
// Happens when message(s) removed from list
listIsIncomplete: false,
selectorMessageSelected: null,
selectorMessageFocused: null,
// message viewer // message viewer
message: null, message: null,
messageViewTrigger: false, error: '',
messageError: '', loading: false,
messageLoading: false, fullScreen: false,
messageFullScreenMode: false,
// Cache mail bodies // Cache mail bodies
messagesBodiesDom: null, bodiesDom: null,
messageActiveDom: null activeDom: null
}); });
this.listDisableAutoSelect = ko.observable(false).extend({ falseTimeout: 500 });
// Computed Observables
addComputablesTo(this, {
listIsLoading: () => {
const value = this.listLoading() | this.listIsIncomplete();
$htmlCL.toggle('list-loading', value);
return value;
},
listPageCount: () => Math.max(1, Math.ceil(this.listCount() / SettingsUserStore.messagesPerPage())),
mainMessageListSearch: {
read: this.listSearch,
write: value => rl.route.setHash(
mailBox(FolderUserStore.currentFolderFullNameHash(), 1, value.toString().trim(), this.listThreadUid())
)
},
isMessageSelected: () => null !== this.message(),
listCheckedOrSelected: () => {
const
selectedMessage = this.selectorMessageSelected(),
focusedMessage = this.selectorMessageFocused(),
checked = this.list.filter(item => isChecked(item) || item === selectedMessage);
return checked.length ? checked : (focusedMessage ? [focusedMessage] : []);
},
listCheckedOrSelectedUidsWithSubMails: () => {
let result = [];
this.listCheckedOrSelected().forEach(message => {
result.push(message.uid);
if (1 < message.threadsLen()) {
result = result.concat(message.threads()).unique();
}
});
return result;
}
});
this.listChecked = koComputable(() => this.list.filter(isChecked))
.extend({ rateLimit: 0 });
this.hasCheckedMessages = koComputable(() => !!this.list.find(isChecked))
.extend({ rateLimit: 0 });
this.hasCheckedOrSelected = koComputable(() => !!(this.selectorMessageSelected()
|| this.selectorMessageFocused()
|| this.list.find(item => item.checked())))
.extend({ rateLimit: 50 });
// Subscribers // Subscribers
addSubscribablesTo(this, { addSubscribablesTo(this, {
message: message => { message: message => {
clearTimeout(MessageSeenTimer); clearTimeout(this.MessageSeenTimer);
elementById('rl-right').classList.toggle('message-selected', !!message);
if (message) { if (message) {
if (!SettingsUserStore.usePreviewPane()) { if (!SettingsUserStore.usePreviewPane()) {
AppUserStore.focusedState(Scope.MessageView); AppUserStore.focusedState(Scope.MessageView);
@ -139,19 +32,17 @@ export const MessageUserStore = new class {
} else { } else {
AppUserStore.focusedState(Scope.MessageList); AppUserStore.focusedState(Scope.MessageList);
this.messageFullScreenMode(false); this.fullScreen(false);
this.hideMessageBodies(); this.hideMessageBodies();
} }
}, },
isMessageSelected: value => elementById('rl-right').classList.toggle('message-selected', value)
}); });
this.purgeMessageBodyCache = this.purgeMessageBodyCache.throttle(30000); this.purgeMessageBodyCache = this.purgeMessageBodyCache.throttle(30000);
} }
purgeMessageBodyCache() { purgeMessageBodyCache() {
const messagesDom = this.messagesBodiesDom(), const messagesDom = this.bodiesDom(),
children = messagesDom && messagesDom.children; children = messagesDom && messagesDom.children;
if (children) { if (children) {
while (15 < children.length) { while (15 < children.length) {
@ -160,390 +51,8 @@ export const MessageUserStore = new class {
} }
} }
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);
}
}
hideMessageBodies() { hideMessageBodies() {
const messagesDom = this.messagesBodiesDom(); const messagesDom = this.bodiesDom();
messagesDom && Array.from(messagesDom.children).forEach(el => el.hidden = true); messagesDom && Array.from(messagesDom.children).forEach(el => el.hidden = true);
} }
/**
* @param {string} fromFolderFullName
* @param {Array} uidForRemove
* @param {string=} toFolderFullName = ''
* @param {boolean=} copy = false
*/
removeMessagesFromList(fromFolderFullName, uidForRemove, toFolderFullName = '', copy = false) {
uidForRemove = uidForRemove.map(mValue => pInt(mValue));
let unseenCount = 0,
messageList = this.list,
currentMessage = this.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 {
this.listIsIncomplete(true);
messages.forEach(item => {
if (currentMessage && currentMessage.hash === item.hash) {
currentMessage = null;
this.message(null);
}
item.deleted(true);
});
setTimeout(() => messages.forEach(item => messageList.remove(item)), 350);
}
}
if (fromFolderFullName) {
setFolderHash(fromFolderFullName, '');
}
if (toFolderFullName) {
setFolderHash(toFolderFullName, '');
}
if (this.listThreadUid()) {
if (
messageList.length &&
!!messageList.find(item => !!(item && item.deleted() && item.uid == this.listThreadUid()))
) {
const message = messageList.find(item => item && !item.deleted());
if (message && this.listThreadUid() != message.uid) {
this.listThreadUid(message.uid);
rl.route.setHash(
mailBox(
FolderUserStore.currentFolderFullNameHash(),
this.listPage(),
this.listSearch(),
this.listThreadUid()
),
true,
true
);
} else if (!message) {
if (1 < this.listPage()) {
this.listPage(this.listPage() - 1);
rl.route.setHash(
mailBox(
FolderUserStore.currentFolderFullNameHash(),
this.listPage(),
this.listSearch(),
this.listThreadUid()
),
true,
true
);
} else {
this.listThreadUid(0);
rl.route.setHash(
mailBox(
FolderUserStore.currentFolderFullNameHash(),
this.listPageBeforeThread(),
this.listSearch()
),
true,
true
);
}
}
}
}
}
setMessage(data, cached, oMessage) {
let isNew = false,
json = data && data.Result,
message = oMessage || this.message();
if (
json &&
MessageModel.validJson(json) &&
message &&
message.folder === json.Folder
) {
const threads = message.threads(),
messagesDom = this.messagesBodiesDom();
if (!oMessage && message.uid != json.Uid && threads.includes(json.Uid)) {
message = MessageModel.reviveFromJson(json);
if (message) {
message.threads(threads);
MessageFlagsCache.initMessage(message);
this.message(this.staticMessage.populateByMessageListItem(message));
message = this.message();
isNew = true;
}
}
if (message && message.uid == json.Uid) {
oMessage || this.messageError('');
/*
if (cached) {
delete json.Flags;
}
*/
isNew || message.revivePropertiesFromJson(json);
addRequestedMessage(message.folder, message.uid);
if (messagesDom) {
let id = 'rl-msg-' + message.hash.replace(/[^a-zA-Z0-9]/g, ''),
body = elementById(id);
if (body) {
message.body = body;
message.isHtml(body.classList.contains('html'));
message.hasImages(body.rlHasImages);
} else {
body = Element.fromHTML('<div id="' + id + '" hidden="" class="b-text-part '
+ (message.pgpSigned() ? ' openpgp-signed' : '')
+ (message.pgpEncrypted() ? ' openpgp-encrypted' : '')
+ '">'
+ '</div>');
message.body = body;
if (!SettingsUserStore.viewHTML() || !message.viewHtml()) {
message.viewPlain();
}
this.purgeMessageBodyCache();
}
messagesDom.append(body);
oMessage || this.messageActiveDom(message.body);
oMessage || this.hideMessageBodies();
oMessage || (message.body.hidden = false);
oMessage && message.viewPopupMessage();
}
MessageFlagsCache.initMessage(message);
if (message.isUnseen()) {
MessageSeenTimer = setTimeout(
() => rl.app.messageListAction(message.folder, MessageSetAction.SetSeen, [message]),
SettingsUserStore.messageReadDelay() * 1000 // seconds
);
}
if (message && isNew) {
let selectedMessage = this.selectorMessageSelected();
if (
selectedMessage &&
(message.folder !== selectedMessage.folder || message.uid != selectedMessage.uid)
) {
this.selectorMessageSelected(null);
if (1 === this.list.length) {
this.selectorMessageFocused(null);
}
} else if (!selectedMessage) {
selectedMessage = this.list.find(
subMessage =>
subMessage &&
subMessage.folder === message.folder &&
subMessage.uid == message.uid
);
if (selectedMessage) {
this.selectorMessageSelected(selectedMessage);
this.selectorMessageFocused(selectedMessage);
}
}
}
}
}
}
selectMessage(oMessage) {
if (oMessage) {
this.message(this.staticMessage.populateByMessageListItem(oMessage));
this.populateMessageBody(this.message());
} else {
this.message(null);
}
}
selectMessageByFolderAndUid(sFolder, iUid) {
if (sFolder && iUid) {
this.message(this.staticMessage.populateByMessageListItem(null));
this.message().folder = sFolder;
this.message().uid = iUid;
this.populateMessageBody(this.message());
} else {
this.message(null);
}
}
populateMessageBody(oMessage, preload) {
if (oMessage) {
preload || this.hideMessageBodies();
preload || this.messageLoading(true);
rl.app.Remote.message((iError, oData, bCached) => {
if (iError) {
if (Notification.RequestAborted !== iError && !preload) {
this.message(null);
this.messageError(getNotification(iError));
}
} else {
this.setMessage(oData, bCached, preload ? oMessage : null);
}
preload || this.messageLoading(false);
}, oMessage.folder, oMessage.uid);
}
}
/**
* @param {Array} list
* @returns {string}
*/
calculateMessageListHash(list) {
return list.map(message => message.hash + '_' + message.threadsLen() + '_' + message.flagHash()).join(
'|'
);
}
reloadFlagsAndCachedMessage() {
this.list.forEach(message => MessageFlagsCache.initMessage(message));
MessageFlagsCache.initMessage(this.message());
this.messageViewTrigger(!this.messageViewTrigger());
}
setMessageList(data, cached) {
const collection = MessageCollectionModel.reviveFromJson(data.Result, cached);
if (collection) {
let unreadCountChange = false;
const
folder = getFolderFromCacheList(collection.Folder);
if (folder && !cached) {
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);
}
this.initUidNextAndNewMessages(folder.fullName, collection.UidNext, collection.NewMessages);
}
this.listCount(collection.MessageResultCount);
this.listSearch(pString(collection.Search));
this.listPage(Math.ceil(collection.Offset / SettingsUserStore.messagesPerPage() + 1));
this.listThreadUid(collection.ThreadUid);
this.listEndHash(
collection.Folder +
'|' + collection.Search +
'|' + this.listThreadUid() +
'|' + this.listPage()
);
this.listEndThreadUid(collection.ThreadUid);
const message = this.message();
if (message && collection.Folder !== message.folder) {
this.message(null);
}
this.listDisableAutoSelect(true);
this.list(collection);
this.listIsIncomplete(false);
clearNewMessageCache();
if (folder && (cached || unreadCountChange || SettingsUserStore.useThreads())) {
rl.app.folderInformation(folder.fullName, collection);
}
} else {
this.listCount(0);
this.list([]);
this.listError(getNotification(Notification.CantGetMessageList));
}
}
}; };

View file

@ -0,0 +1,435 @@
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());
};

View file

@ -2,7 +2,7 @@ import { koComputable } from 'External/ko';
import { i18n, trigger as translatorTrigger } from 'Common/Translator'; import { i18n, trigger as translatorTrigger } from 'Common/Translator';
import { MessageUserStore } from 'Stores/User/Message'; import { MessagelistUserStore } from 'Stores/User/Messagelist';
import { AbstractViewPopup } from 'Knoin/AbstractViews'; import { AbstractViewPopup } from 'Knoin/AbstractViews';
import { FolderUserStore } from 'Stores/User/Folder'; import { FolderUserStore } from 'Stores/User/Folder';
@ -54,7 +54,7 @@ class AdvancedSearchPopupView extends AbstractViewPopup {
submitForm() { submitForm() {
const search = this.buildSearchString(); const search = this.buildSearchString();
if (search) { if (search) {
MessageUserStore.mainMessageListSearch(search); MessagelistUserStore.mainSearch(search);
} }
this.cancelCommand(); this.cancelCommand();

View file

@ -18,9 +18,9 @@ import { encodeHtml, HtmlEditor, htmlToPlain } from 'Common/Html';
import { koArrayWithDestroy } from 'External/ko'; import { koArrayWithDestroy } from 'External/ko';
import { UNUSED_OPTION_VALUE } from 'Common/Consts'; import { UNUSED_OPTION_VALUE } from 'Common/Consts';
import { messagesDeleteHelper } from 'Common/Folders';
import { serverRequest } from 'Common/Links'; import { serverRequest } from 'Common/Links';
import { i18n, getNotification, getUploadErrorDescByCode } from 'Common/Translator'; import { i18n, getNotification, getUploadErrorDescByCode, timestampToString } from 'Common/Translator';
import { timestampToString } from 'Common/Momentor';
import { MessageFlagsCache, setFolderHash } from 'Common/Cache'; import { MessageFlagsCache, setFolderHash } from 'Common/Cache';
import { doc, Settings, SettingsGet, getFullscreenElement, exitFullscreen, elementById } from 'Common/Globals'; import { doc, Settings, SettingsGet, getFullscreenElement, exitFullscreen, elementById } from 'Common/Globals';
@ -33,6 +33,7 @@ import { PgpUserStore } from 'Stores/User/Pgp';
import { OpenPGPUserStore } from 'Stores/User/OpenPGP'; import { OpenPGPUserStore } from 'Stores/User/OpenPGP';
import { GnuPGUserStore } from 'Stores/User/GnuPG'; import { GnuPGUserStore } from 'Stores/User/GnuPG';
import { MessageUserStore } from 'Stores/User/Message'; import { MessageUserStore } from 'Stores/User/Message';
import { MessagelistUserStore } from 'Stores/User/Messagelist';
import Remote from 'Remote/User/Fetch'; import Remote from 'Remote/User/Fetch';
@ -521,7 +522,7 @@ class ComposePopupView extends AbstractViewPopup {
if (isArray(flagsCache)) { if (isArray(flagsCache)) {
flagsCache.push(('forward' === this.aDraftInfo[0]) ? '$forwarded' : '\\answered'); flagsCache.push(('forward' === this.aDraftInfo[0]) ? '$forwarded' : '\\answered');
MessageFlagsCache.setFor(this.aDraftInfo[2], this.aDraftInfo[1], flagsCache); MessageFlagsCache.setFor(this.aDraftInfo[2], this.aDraftInfo[1], flagsCache);
MessageUserStore.reloadFlagsAndCachedMessage(); MessagelistUserStore.reloadFlagsAndCachedMessage();
setFolderHash(this.aDraftInfo[2], ''); setFolderHash(this.aDraftInfo[2], '');
} }
} }
@ -632,8 +633,8 @@ class ComposePopupView extends AbstractViewPopup {
const const
sFromFolderFullName = this.draftsFolder(), sFromFolderFullName = this.draftsFolder(),
aUidForRemove = [this.draftUid()]; aUidForRemove = [this.draftUid()];
rl.app.messagesDeleteHelper(sFromFolderFullName, aUidForRemove); messagesDeleteHelper(sFromFolderFullName, aUidForRemove);
MessageUserStore.removeMessagesFromList(sFromFolderFullName, aUidForRemove); MessagelistUserStore.removeMessagesFromList(sFromFolderFullName, aUidForRemove);
this.closeCommand(); this.closeCommand();
} }
} }
@ -684,8 +685,18 @@ class ComposePopupView extends AbstractViewPopup {
}, 60000); }, 60000);
} }
// getAutocomplete
emailsSource(oData, fResponse) { emailsSource(oData, fResponse) {
rl.app.getAutocomplete(oData.term, aData => fResponse(aData.map(oEmailItem => oEmailItem.toLine(false)))); Remote.suggestions((iError, data) => {
if (!iError && isArray(data.Result)) {
fResponse(
data.Result.map(item => (item && item[0] ? (new EmailModel(item[0], item[1])).toLine(false) : null))
.filter(v => v)
);
} else if (Notification.RequestAborted !== iError) {
fResponse([]);
}
}, oData.term);
} }
reloadDraftFolder() { reloadDraftFolder() {
@ -693,7 +704,7 @@ class ComposePopupView extends AbstractViewPopup {
if (draftsFolder && UNUSED_OPTION_VALUE !== draftsFolder) { if (draftsFolder && UNUSED_OPTION_VALUE !== draftsFolder) {
setFolderHash(draftsFolder, ''); setFolderHash(draftsFolder, '');
if (FolderUserStore.currentFolderFullName() === draftsFolder) { if (FolderUserStore.currentFolderFullName() === draftsFolder) {
rl.app.reloadMessageList(true); MessagelistUserStore.reload(true);
} else { } else {
rl.app.folderInformation(draftsFolder); rl.app.folderInformation(draftsFolder);
} }

View file

@ -11,7 +11,7 @@ import { SieveUserStore } from 'Stores/User/Sieve';
import { AbstractViewPopup } from 'Knoin/AbstractViews'; import { AbstractViewPopup } from 'Knoin/AbstractViews';
import { folderListOptionsBuilder } from 'Common/UtilsUser'; import { folderListOptionsBuilder } from 'Common/Folders';
class FilterPopupView extends AbstractViewPopup { class FilterPopupView extends AbstractViewPopup {
constructor() { constructor() {

View file

@ -2,6 +2,7 @@ import { i18n, getNotification } from 'Common/Translator';
import { setFolderHash } from 'Common/Cache'; import { setFolderHash } from 'Common/Cache';
import { MessageUserStore } from 'Stores/User/Message'; import { MessageUserStore } from 'Stores/User/Message';
import { MessagelistUserStore } from 'Stores/User/Messagelist';
import Remote from 'Remote/User/Fetch'; import Remote from 'Remote/User/Fetch';
@ -38,7 +39,7 @@ class FolderClearPopupView extends AbstractViewPopup {
const folderToClear = this.selectedFolder(); const folderToClear = this.selectedFolder();
if (folderToClear) { if (folderToClear) {
MessageUserStore.message(null); MessageUserStore.message(null);
MessageUserStore.list([]); MessagelistUserStore([]);
this.clearingProcess(true); this.clearingProcess(true);
@ -52,7 +53,7 @@ class FolderClearPopupView extends AbstractViewPopup {
if (iError) { if (iError) {
this.clearingError(getNotification(iError)); this.clearingError(getNotification(iError));
} else { } else {
rl.app.reloadMessageList(true); MessagelistUserStore.reload(true);
this.cancelCommand(); this.cancelCommand();
} }
}, { }, {

View file

@ -3,7 +3,7 @@ import { koComputable } from 'External/ko';
import { Notification } from 'Common/Enums'; import { Notification } from 'Common/Enums';
import { UNUSED_OPTION_VALUE } from 'Common/Consts'; import { UNUSED_OPTION_VALUE } from 'Common/Consts';
import { defaultOptionsAfterRender } from 'Common/Utils'; import { defaultOptionsAfterRender } from 'Common/Utils';
import { folderListOptionsBuilder, sortFolders } from 'Common/UtilsUser'; import { folderListOptionsBuilder, sortFolders } from 'Common/Folders';
import { getNotification } from 'Common/Translator'; import { getNotification } from 'Common/Translator';
import { FolderUserStore } from 'Stores/User/Folder'; import { FolderUserStore } from 'Stores/User/Folder';

View file

@ -4,7 +4,7 @@ import { koComputable, addSubscribablesTo } from 'External/ko';
import { SetSystemFoldersNotification } from 'Common/EnumsUser'; import { SetSystemFoldersNotification } from 'Common/EnumsUser';
import { UNUSED_OPTION_VALUE } from 'Common/Consts'; import { UNUSED_OPTION_VALUE } from 'Common/Consts';
import { defaultOptionsAfterRender } from 'Common/Utils'; import { defaultOptionsAfterRender } from 'Common/Utils';
import { folderListOptionsBuilder } from 'Common/UtilsUser'; import { folderListOptionsBuilder } from 'Common/Folders';
import { initOnStartOrLangChange, i18n } from 'Common/Translator'; import { initOnStartOrLangChange, i18n } from 'Common/Translator';
import { FolderUserStore } from 'Stores/User/Folder'; import { FolderUserStore } from 'Stores/User/Folder';

View file

@ -10,6 +10,7 @@ import { AppUserStore } from 'Stores/User/App';
import { SettingsUserStore } from 'Stores/User/Settings'; import { SettingsUserStore } from 'Stores/User/Settings';
import { FolderUserStore } from 'Stores/User/Folder'; import { FolderUserStore } from 'Stores/User/Folder';
import { MessageUserStore } from 'Stores/User/Message'; import { MessageUserStore } from 'Stores/User/Message';
import { MessagelistUserStore } from 'Stores/User/Messagelist';
import { showScreenPopup } from 'Knoin/Knoin'; import { showScreenPopup } from 'Knoin/Knoin';
import { AbstractViewLeft } from 'Knoin/AbstractViews'; import { AbstractViewLeft } from 'Knoin/AbstractViews';
@ -22,6 +23,8 @@ import { isArray } from 'Common/Utils';
import { ClientSideKeyName } from 'Common/EnumsUser'; import { ClientSideKeyName } from 'Common/EnumsUser';
import * as Local from 'Storage/Client'; import * as Local from 'Storage/Client';
import { moveMessagesToFolder } from 'Common/Folders';
/** /**
* @param {string} sFullName * @param {string} sFullName
* @param {boolean} bExpanded * @param {boolean} bExpanded
@ -109,9 +112,9 @@ export class MailFolderList extends AbstractViewLeft {
if (folder) { if (folder) {
if (moveAction()) { if (moveAction()) {
moveAction(false); moveAction(false);
rl.app.moveMessagesToFolder( moveMessagesToFolder(
FolderUserStore.currentFolderFullName(), FolderUserStore.currentFolderFullName(),
MessageUserStore.listCheckedOrSelectedUidsWithSubMails(), MessagelistUserStore.listCheckedOrSelectedUidsWithSubMails(),
folder.fullName, folder.fullName,
event.ctrlKey event.ctrlKey
); );

View file

@ -15,8 +15,9 @@ import { UNUSED_OPTION_VALUE } from 'Common/Consts';
import { doc, leftPanelDisabled, moveAction, Settings, SettingsCapa, SettingsGet, fireEvent } from 'Common/Globals'; import { doc, leftPanelDisabled, moveAction, Settings, SettingsCapa, SettingsGet, fireEvent } from 'Common/Globals';
import { computedPaginatorHelper, showMessageComposer, folderListOptionsBuilder } from 'Common/UtilsUser'; import { computedPaginatorHelper, showMessageComposer, populateMessageBody } from 'Common/UtilsUser';
import { FileInfo } from 'Common/File'; import { FileInfo } from 'Common/File';
import { folderListOptionsBuilder, moveMessagesToFolder } from 'Common/Folders';
import { mailBox, serverRequest } from 'Common/Links'; import { mailBox, serverRequest } from 'Common/Links';
import { Selector } from 'Common/Selector'; import { Selector } from 'Common/Selector';
@ -34,6 +35,7 @@ import { AppUserStore } from 'Stores/User/App';
import { SettingsUserStore } from 'Stores/User/Settings'; import { SettingsUserStore } from 'Stores/User/Settings';
import { FolderUserStore } from 'Stores/User/Folder'; import { FolderUserStore } from 'Stores/User/Folder';
import { MessageUserStore } from 'Stores/User/Message'; import { MessageUserStore } from 'Stores/User/Message';
import { MessagelistUserStore } from 'Stores/User/Messagelist';
import { ThemeStore } from 'Stores/Theme'; import { ThemeStore } from 'Stores/Theme';
import Remote from 'Remote/User/Fetch'; import Remote from 'Remote/User/Fetch';
@ -44,8 +46,18 @@ import { AbstractViewRight } from 'Knoin/AbstractViews';
import { FolderClearPopupView } from 'View/Popup/FolderClear'; import { FolderClearPopupView } from 'View/Popup/FolderClear';
import { AdvancedSearchPopupView } from 'View/Popup/AdvancedSearch'; import { AdvancedSearchPopupView } from 'View/Popup/AdvancedSearch';
import { MessageModel } from 'Model/Message';
const const
canBeMovedHelper = () => MessageUserStore.hasCheckedOrSelected(); canBeMovedHelper = () => MessagelistUserStore.hasCheckedOrSelected(),
/**
* @param {string} sFolderFullName
* @param {number} iSetAction
* @param {Array=} aMessages = null
* @returns {void}
*/
listAction = (...args) => MessagelistUserStore.setAction(...args);
export class MailMessageList extends AbstractViewRight { export class MailMessageList extends AbstractViewRight {
constructor() { constructor() {
@ -62,23 +74,23 @@ export class MailMessageList extends AbstractViewRight {
this.allowSearchAdv = SettingsCapa(Capa.SearchAdv); this.allowSearchAdv = SettingsCapa(Capa.SearchAdv);
this.allowDangerousActions = SettingsCapa(Capa.DangerousActions); this.allowDangerousActions = SettingsCapa(Capa.DangerousActions);
this.messageList = MessageUserStore.list; this.messageList = MessagelistUserStore;
this.composeInEdit = AppUserStore.composeInEdit; this.composeInEdit = AppUserStore.composeInEdit;
this.isMobile = ThemeStore.isMobile; this.isMobile = ThemeStore.isMobile;
this.leftPanelDisabled = leftPanelDisabled; this.leftPanelDisabled = leftPanelDisabled;
this.messageListSearch = MessageUserStore.listSearch; this.messageListSearch = MessagelistUserStore.listSearch;
this.messageListError = MessageUserStore.listError; this.messageListError = MessagelistUserStore.error;
this.popupVisibility = arePopupsVisible; this.popupVisibility = arePopupsVisible;
this.useCheckboxesInList = SettingsUserStore.useCheckboxesInList; this.useCheckboxesInList = SettingsUserStore.useCheckboxesInList;
this.messageListThreadUid = MessageUserStore.listEndThreadUid; this.messageListThreadUid = MessagelistUserStore.endThreadUid;
this.messageListIsLoading = MessageUserStore.listIsLoading; this.messageListIsLoading = MessagelistUserStore.isLoading;
initOnStartOrLangChange(() => this.emptySubjectValue = i18n('MESSAGE_LIST/EMPTY_SUBJECT_TEXT')); initOnStartOrLangChange(() => this.emptySubjectValue = i18n('MESSAGE_LIST/EMPTY_SUBJECT_TEXT'));
@ -114,44 +126,44 @@ export class MailMessageList extends AbstractViewRight {
), ),
messageListSearchDesc: () => { messageListSearchDesc: () => {
const value = MessageUserStore.list().Search; const value = MessagelistUserStore().Search;
return value ? i18n('MESSAGE_LIST/SEARCH_RESULT_FOR', { SEARCH: value }) : '' return value ? i18n('MESSAGE_LIST/SEARCH_RESULT_FOR', { SEARCH: value }) : ''
}, },
messageListPaginator: computedPaginatorHelper(MessageUserStore.listPage, messageListPaginator: computedPaginatorHelper(MessagelistUserStore.page,
MessageUserStore.listPageCount), MessagelistUserStore.pageCount),
checkAll: { checkAll: {
read: () => 0 < MessageUserStore.listChecked().length, read: () => 0 < MessagelistUserStore.listChecked().length,
write: (value) => { write: (value) => {
value = !!value; value = !!value;
MessageUserStore.list.forEach(message => message.checked(value)); MessagelistUserStore.forEach(message => message.checked(value));
} }
}, },
inputProxyMessageListSearch: { inputProxyMessageListSearch: {
read: MessageUserStore.mainMessageListSearch, read: MessagelistUserStore.mainSearch,
write: value => this.sLastSearchValue = value write: value => this.sLastSearchValue = value
}, },
isIncompleteChecked: () => { isIncompleteChecked: () => {
const c = MessageUserStore.listChecked().length; const c = MessagelistUserStore.listChecked().length;
return c && MessageUserStore.list.length > c; return c && MessagelistUserStore().length > c;
}, },
hasMessages: () => 0 < MessageUserStore.list().length, hasMessages: () => 0 < MessagelistUserStore().length,
isSpamFolder: () => (FolderUserStore.spamFolder() || 0) === MessageUserStore.list().Folder, isSpamFolder: () => (FolderUserStore.spamFolder() || 0) === MessagelistUserStore().Folder,
isSpamDisabled: () => UNUSED_OPTION_VALUE === FolderUserStore.spamFolder(), isSpamDisabled: () => UNUSED_OPTION_VALUE === FolderUserStore.spamFolder(),
isTrashFolder: () => (FolderUserStore.trashFolder() || 0) === MessageUserStore.list().Folder, isTrashFolder: () => (FolderUserStore.trashFolder() || 0) === MessagelistUserStore().Folder,
isDraftFolder: () => (FolderUserStore.draftsFolder() || 0) === MessageUserStore.list().Folder, isDraftFolder: () => (FolderUserStore.draftsFolder() || 0) === MessagelistUserStore().Folder,
isSentFolder: () => (FolderUserStore.sentFolder() || 0) === MessageUserStore.list().Folder, isSentFolder: () => (FolderUserStore.sentFolder() || 0) === MessagelistUserStore().Folder,
isArchiveFolder: () => (FolderUserStore.archiveFolder() || 0) === MessageUserStore.list().Folder, isArchiveFolder: () => (FolderUserStore.archiveFolder() || 0) === MessagelistUserStore().Folder,
isArchiveDisabled: () => UNUSED_OPTION_VALUE === FolderUserStore.archiveFolder(), isArchiveDisabled: () => UNUSED_OPTION_VALUE === FolderUserStore.archiveFolder(),
@ -163,9 +175,9 @@ export class MailMessageList extends AbstractViewRight {
isUnSpamVisible: () => isUnSpamVisible: () =>
this.isSpamFolder() && !this.isSpamDisabled() && !this.isDraftFolder() && !this.isSentFolder(), this.isSpamFolder() && !this.isSpamDisabled() && !this.isDraftFolder() && !this.isSentFolder(),
mobileCheckedStateShow: () => ThemeStore.isMobile() ? 0 < MessageUserStore.listChecked().length : true, mobileCheckedStateShow: () => ThemeStore.isMobile() ? 0 < MessagelistUserStore.listChecked().length : true,
mobileCheckedStateHide: () => ThemeStore.isMobile() ? !MessageUserStore.listChecked().length : true, mobileCheckedStateHide: () => ThemeStore.isMobile() ? !MessagelistUserStore.listChecked().length : true,
sortText: () => { sortText: () => {
let mode = FolderUserStore.sortMode(), let mode = FolderUserStore.sortMode(),
@ -181,20 +193,27 @@ export class MailMessageList extends AbstractViewRight {
} }
}); });
this.hasCheckedOrSelectedLines = MessageUserStore.hasCheckedOrSelected, this.hasCheckedOrSelectedLines = MessagelistUserStore.hasCheckedOrSelected,
this.selector = new Selector( this.selector = new Selector(
MessageUserStore.list, MessagelistUserStore,
MessageUserStore.selectorMessageSelected, MessagelistUserStore.selectedMessage,
MessageUserStore.selectorMessageFocused, MessagelistUserStore.focusedMessage,
'.messageListItem .actionHandle', '.messageListItem .actionHandle',
'.messageListItem .checkboxMessage', '.messageListItem .checkboxMessage',
'.messageListItem.focused' '.messageListItem.focused'
); );
this.selector.on('ItemSelect', message => MessageUserStore.selectMessage(message)); this.selector.on('ItemSelect', message => {
if (message) {
MessageUserStore.message(MessageModel.fromMessageListItem(message));
populateMessageBody(MessageUserStore.message());
} else {
MessageUserStore.message(null);
}
});
this.selector.on('MiddleClick', message => MessageUserStore.populateMessageBody(message, true)); this.selector.on('MiddleClick', message => populateMessageBody(message, true));
this.selector.on('ItemGetUid', message => (message ? message.generateUid() : '')); this.selector.on('ItemGetUid', message => (message ? message.generateUid() : ''));
@ -213,7 +232,7 @@ export class MailMessageList extends AbstractViewRight {
addEventListener('mailbox.message.show', e => { addEventListener('mailbox.message.show', e => {
const sFolder = e.detail.Folder, iUid = e.detail.Uid; const sFolder = e.detail.Folder, iUid = e.detail.Uid;
const message = MessageUserStore.list.find( const message = MessagelistUserStore.find(
item => item && sFolder === item.folder && iUid == item.uid item => item && sFolder === item.folder && iUid == item.uid
); );
@ -227,12 +246,19 @@ export class MailMessageList extends AbstractViewRight {
if ('INBOX' !== sFolder) { if ('INBOX' !== sFolder) {
rl.route.setHash(mailBox(sFolder)); rl.route.setHash(mailBox(sFolder));
} }
if (sFolder && iUid) {
MessageUserStore.message(MessageModel.fromMessageListItem(null));
MessageUserStore.message().folder = sFolder;
MessageUserStore.message().uid = iUid;
MessageUserStore.selectMessageByFolderAndUid(sFolder, iUid); populateMessageBody(MessageUserStore.message());
} else {
MessageUserStore.message(null);
}
} }
}); });
MessageUserStore.listEndHash.subscribe((() => MessagelistUserStore.endHash.subscribe((() =>
this.selector.scrollToFocused() this.selector.scrollToFocused()
).throttle(50)); ).throttle(50));
@ -260,15 +286,15 @@ export class MailMessageList extends AbstractViewRight {
} }
reload() { reload() {
if (!MessageUserStore.listIsLoading()) { if (!MessagelistUserStore.isLoading()) {
rl.app.reloadMessageList(false, true); MessagelistUserStore.reload(false, true);
} }
} }
multyForwardCommand() { multyForwardCommand() {
showMessageComposer([ showMessageComposer([
ComposeType.ForwardAsAttachment, ComposeType.ForwardAsAttachment,
MessageUserStore.listCheckedOrSelected() MessagelistUserStore.listCheckedOrSelected()
]); ]);
} }
@ -277,7 +303,7 @@ export class MailMessageList extends AbstractViewRight {
rl.app.deleteMessagesFromFolder( rl.app.deleteMessagesFromFolder(
FolderType.Trash, FolderType.Trash,
FolderUserStore.currentFolderFullName(), FolderUserStore.currentFolderFullName(),
MessageUserStore.listCheckedOrSelectedUidsWithSubMails(), MessagelistUserStore.listCheckedOrSelectedUidsWithSubMails(),
false false
); );
} }
@ -287,7 +313,7 @@ export class MailMessageList extends AbstractViewRight {
rl.app.deleteMessagesFromFolder( rl.app.deleteMessagesFromFolder(
FolderType.Trash, FolderType.Trash,
FolderUserStore.currentFolderFullName(), FolderUserStore.currentFolderFullName(),
MessageUserStore.listCheckedOrSelectedUidsWithSubMails(), MessagelistUserStore.listCheckedOrSelectedUidsWithSubMails(),
true true
); );
} }
@ -296,7 +322,7 @@ export class MailMessageList extends AbstractViewRight {
rl.app.deleteMessagesFromFolder( rl.app.deleteMessagesFromFolder(
FolderType.Archive, FolderType.Archive,
FolderUserStore.currentFolderFullName(), FolderUserStore.currentFolderFullName(),
MessageUserStore.listCheckedOrSelectedUidsWithSubMails(), MessagelistUserStore.listCheckedOrSelectedUidsWithSubMails(),
true true
); );
} }
@ -305,7 +331,7 @@ export class MailMessageList extends AbstractViewRight {
rl.app.deleteMessagesFromFolder( rl.app.deleteMessagesFromFolder(
FolderType.Spam, FolderType.Spam,
FolderUserStore.currentFolderFullName(), FolderUserStore.currentFolderFullName(),
MessageUserStore.listCheckedOrSelectedUidsWithSubMails(), MessagelistUserStore.listCheckedOrSelectedUidsWithSubMails(),
true true
); );
} }
@ -314,7 +340,7 @@ export class MailMessageList extends AbstractViewRight {
rl.app.deleteMessagesFromFolder( rl.app.deleteMessagesFromFolder(
FolderType.NotSpam, FolderType.NotSpam,
FolderUserStore.currentFolderFullName(), FolderUserStore.currentFolderFullName(),
MessageUserStore.listCheckedOrSelectedUidsWithSubMails(), MessagelistUserStore.listCheckedOrSelectedUidsWithSubMails(),
true true
); );
} }
@ -339,7 +365,7 @@ export class MailMessageList extends AbstractViewRight {
} }
goToUpOrDown(up) { goToUpOrDown(up) {
if (MessageUserStore.listChecked().length) { if (MessagelistUserStore.listChecked().length) {
return false; return false;
} }
@ -384,27 +410,28 @@ export class MailMessageList extends AbstractViewRight {
} }
useAutoSelect() { useAutoSelect() {
return !MessageUserStore.listDisableAutoSelect() return !MessagelistUserStore.disableAutoSelect()
&& !/is:unseen/.test(MessageUserStore.mainMessageListSearch()) && !/is:unseen/.test(MessagelistUserStore.mainSearch())
&& SettingsUserStore.usePreviewPane(); && SettingsUserStore.usePreviewPane();
} }
searchEnterAction() { searchEnterAction() {
MessageUserStore.mainMessageListSearch(this.sLastSearchValue); MessagelistUserStore.mainSearch(this.sLastSearchValue);
this.inputMessageListSearchFocus(false); this.inputMessageListSearchFocus(false);
} }
cancelSearch() { cancelSearch() {
MessageUserStore.mainMessageListSearch(''); MessagelistUserStore.mainSearch('');
this.inputMessageListSearchFocus(false); this.inputMessageListSearchFocus(false);
} }
cancelThreadUid() { cancelThreadUid() {
// history.go(-1) better?
rl.route.setHash( rl.route.setHash(
mailBox( mailBox(
FolderUserStore.currentFolderFullNameHash(), FolderUserStore.currentFolderFullNameHash(),
MessageUserStore.listPageBeforeThread(), MessagelistUserStore.pageBeforeThread(),
MessageUserStore.listSearch() MessagelistUserStore.listSearch()
) )
); );
} }
@ -415,10 +442,10 @@ export class MailMessageList extends AbstractViewRight {
* @returns {boolean} * @returns {boolean}
*/ */
moveSelectedMessagesToFolder(sToFolderFullName, bCopy) { moveSelectedMessagesToFolder(sToFolderFullName, bCopy) {
if (MessageUserStore.hasCheckedOrSelected()) { if (MessagelistUserStore.hasCheckedOrSelected()) {
rl.app.moveMessagesToFolder( moveMessagesToFolder(
FolderUserStore.currentFolderFullName(), FolderUserStore.currentFolderFullName(),
MessageUserStore.listCheckedOrSelectedUidsWithSubMails(), MessagelistUserStore.listCheckedOrSelectedUidsWithSubMails(),
sToFolderFullName, sToFolderFullName,
bCopy bCopy
); );
@ -430,7 +457,7 @@ export class MailMessageList extends AbstractViewRight {
getDragData(event) { getDragData(event) {
const item = ko.dataFor(doc.elementFromPoint(event.clientX, event.clientY)); const item = ko.dataFor(doc.elementFromPoint(event.clientX, event.clientY));
item && item.checked && item.checked(true); item && item.checked && item.checked(true);
const uids = MessageUserStore.listCheckedOrSelectedUidsWithSubMails(); const uids = MessagelistUserStore.listCheckedOrSelectedUidsWithSubMails();
item && !uids.includes(item.uid) && uids.push(item.uid); item && !uids.includes(item.uid) && uids.push(item.uid);
return uids.length ? { return uids.length ? {
copy: event.ctrlKey, copy: event.ctrlKey,
@ -439,34 +466,24 @@ export class MailMessageList extends AbstractViewRight {
} : null; } : null;
} }
/**
* @param {string} sFolderFullName
* @param {number} iSetAction
* @param {Array=} aMessages = null
* @returns {void}
*/
setAction(sFolderFullName, iSetAction, aMessages) {
rl.app.messageListAction(sFolderFullName, iSetAction, aMessages);
}
listSetSeen() { listSetSeen() {
this.setAction( listAction(
FolderUserStore.currentFolderFullName(), FolderUserStore.currentFolderFullName(),
MessageSetAction.SetSeen, MessageSetAction.SetSeen,
MessageUserStore.listCheckedOrSelected() MessagelistUserStore.listCheckedOrSelected()
); );
} }
listSetAllSeen() { listSetAllSeen() {
let sFolderFullName = FolderUserStore.currentFolderFullName(), let sFolderFullName = FolderUserStore.currentFolderFullName(),
iThreadUid = MessageUserStore.listEndThreadUid(); iThreadUid = MessagelistUserStore.endThreadUid();
if (sFolderFullName) { if (sFolderFullName) {
let cnt = 0; let cnt = 0;
const uids = []; const uids = [];
let folder = getFolderFromCacheList(sFolderFullName); let folder = getFolderFromCacheList(sFolderFullName);
if (folder) { if (folder) {
MessageUserStore.list.forEach(message => { MessagelistUserStore.forEach(message => {
if (message.isUnseen()) { if (message.isUnseen()) {
++cnt; ++cnt;
} }
@ -486,47 +503,47 @@ export class MailMessageList extends AbstractViewRight {
Remote.messageSetSeenToAll(sFolderFullName, true, iThreadUid ? uids : null); Remote.messageSetSeenToAll(sFolderFullName, true, iThreadUid ? uids : null);
MessageUserStore.reloadFlagsAndCachedMessage(); MessagelistUserStore.reloadFlagsAndCachedMessage();
} }
} }
} }
listUnsetSeen() { listUnsetSeen() {
this.setAction( listAction(
FolderUserStore.currentFolderFullName(), FolderUserStore.currentFolderFullName(),
MessageSetAction.UnsetSeen, MessageSetAction.UnsetSeen,
MessageUserStore.listCheckedOrSelected() MessagelistUserStore.listCheckedOrSelected()
); );
} }
listSetFlags() { listSetFlags() {
this.setAction( listAction(
FolderUserStore.currentFolderFullName(), FolderUserStore.currentFolderFullName(),
MessageSetAction.SetFlag, MessageSetAction.SetFlag,
MessageUserStore.listCheckedOrSelected() MessagelistUserStore.listCheckedOrSelected()
); );
} }
listUnsetFlags() { listUnsetFlags() {
this.setAction( listAction(
FolderUserStore.currentFolderFullName(), FolderUserStore.currentFolderFullName(),
MessageSetAction.UnsetFlag, MessageSetAction.UnsetFlag,
MessageUserStore.listCheckedOrSelected() MessagelistUserStore.listCheckedOrSelected()
); );
} }
flagMessages(currentMessage) { flagMessages(currentMessage) {
const checked = MessageUserStore.listCheckedOrSelected(); const checked = MessagelistUserStore.listCheckedOrSelected();
if (currentMessage) { if (currentMessage) {
const checkedUids = checked.map(message => message.uid); const checkedUids = checked.map(message => message.uid);
if (checkedUids.includes(currentMessage.uid)) { if (checkedUids.includes(currentMessage.uid)) {
this.setAction( listAction(
currentMessage.folder, currentMessage.folder,
currentMessage.isFlagged() ? MessageSetAction.UnsetFlag : MessageSetAction.SetFlag, currentMessage.isFlagged() ? MessageSetAction.UnsetFlag : MessageSetAction.SetFlag,
checked checked
); );
} else { } else {
this.setAction( listAction(
currentMessage.folder, currentMessage.folder,
currentMessage.isFlagged() ? MessageSetAction.UnsetFlag : MessageSetAction.SetFlag, currentMessage.isFlagged() ? MessageSetAction.UnsetFlag : MessageSetAction.SetFlag,
[currentMessage] [currentMessage]
@ -536,17 +553,17 @@ export class MailMessageList extends AbstractViewRight {
} }
flagMessagesFast(bFlag) { flagMessagesFast(bFlag) {
const checked = MessageUserStore.listCheckedOrSelected(); const checked = MessagelistUserStore.listCheckedOrSelected();
if (checked.length) { if (checked.length) {
if (undefined === bFlag) { if (undefined === bFlag) {
const flagged = checked.filter(message => message.isFlagged()); const flagged = checked.filter(message => message.isFlagged());
this.setAction( listAction(
checked[0].folder, checked[0].folder,
checked.length === flagged.length ? MessageSetAction.UnsetFlag : MessageSetAction.SetFlag, checked.length === flagged.length ? MessageSetAction.UnsetFlag : MessageSetAction.SetFlag,
checked checked
); );
} else { } else {
this.setAction( listAction(
checked[0].folder, checked[0].folder,
!bFlag ? MessageSetAction.UnsetFlag : MessageSetAction.SetFlag, !bFlag ? MessageSetAction.UnsetFlag : MessageSetAction.SetFlag,
checked checked
@ -556,17 +573,17 @@ export class MailMessageList extends AbstractViewRight {
} }
seenMessagesFast(seen) { seenMessagesFast(seen) {
const checked = MessageUserStore.listCheckedOrSelected(); const checked = MessagelistUserStore.listCheckedOrSelected();
if (checked.length) { if (checked.length) {
if (undefined === seen) { if (undefined === seen) {
const unseen = checked.filter(message => message.isUnseen()); const unseen = checked.filter(message => message.isUnseen());
this.setAction( listAction(
checked[0].folder, checked[0].folder,
unseen.length ? MessageSetAction.SetSeen : MessageSetAction.UnsetSeen, unseen.length ? MessageSetAction.SetSeen : MessageSetAction.UnsetSeen,
checked checked
); );
} else { } else {
this.setAction( listAction(
checked[0].folder, checked[0].folder,
seen ? MessageSetAction.SetSeen : MessageSetAction.UnsetSeen, seen ? MessageSetAction.SetSeen : MessageSetAction.UnsetSeen,
checked checked
@ -580,28 +597,28 @@ export class MailMessageList extends AbstractViewRight {
mailBox( mailBox(
FolderUserStore.currentFolderFullNameHash(), FolderUserStore.currentFolderFullNameHash(),
page.value, page.value,
MessageUserStore.listSearch(), MessagelistUserStore.listSearch(),
MessageUserStore.listThreadUid() MessagelistUserStore.threadUid()
) )
); );
} }
gotoThread(message) { gotoThread(message) {
if (message && 0 < message.threadsLen()) { if (message && 0 < message.threadsLen()) {
MessageUserStore.listPageBeforeThread(MessageUserStore.listPage()); MessagelistUserStore.pageBeforeThread(MessagelistUserStore.page());
rl.route.setHash( rl.route.setHash(
mailBox(FolderUserStore.currentFolderFullNameHash(), 1, MessageUserStore.listSearch(), message.uid) mailBox(FolderUserStore.currentFolderFullNameHash(), 1, MessagelistUserStore.listSearch(), message.uid)
); );
} }
} }
listEmptyMessage() { listEmptyMessage() {
if (!this.dragOver() if (!this.dragOver()
&& !MessageUserStore.list().length && !MessagelistUserStore().length
&& !MessageUserStore.listIsLoading() && !MessagelistUserStore.isLoading()
&& !MessageUserStore.listError()) { && !MessagelistUserStore.error()) {
return i18n('MESSAGE_LIST/EMPTY_' + (MessageUserStore.listSearch() ? 'SEARCH_' : '') + 'LIST'); return i18n('MESSAGE_LIST/EMPTY_' + (MessagelistUserStore.listSearch() ? 'SEARCH_' : '') + 'LIST');
} }
return ''; return '';
} }
@ -609,9 +626,9 @@ export class MailMessageList extends AbstractViewRight {
clearListIsVisible() { clearListIsVisible() {
return ( return (
!this.messageListSearchDesc() && !this.messageListSearchDesc() &&
!MessageUserStore.listError() && !MessagelistUserStore.error() &&
!MessageUserStore.listEndThreadUid() && !MessagelistUserStore.endThreadUid() &&
MessageUserStore.list().length && MessagelistUserStore().length &&
(this.isSpamFolder() || this.isTrashFolder()) (this.isSpamFolder() || this.isTrashFolder())
); );
} }
@ -668,13 +685,13 @@ export class MailMessageList extends AbstractViewRight {
.on('onBodyDragLeave', () => this.dragOver(false)) .on('onBodyDragLeave', () => this.dragOver(false))
.on('onSelect', (sUid, oData) => { .on('onSelect', (sUid, oData) => {
if (sUid && oData && 'message/rfc822' === oData.Type) { if (sUid && oData && 'message/rfc822' === oData.Type) {
MessageUserStore.listLoading(true); MessagelistUserStore.loading(true);
return true; return true;
} }
return false; return false;
}) })
.on('onComplete', () => rl.app.reloadMessageList(true, true)); .on('onComplete', () => MessagelistUserStore.reload(true, true));
} }
// initShortcuts // initShortcuts
@ -694,12 +711,12 @@ export class MailMessageList extends AbstractViewRight {
// delete // delete
shortcuts.add('delete', 'shift', Scope.MessageList, () => { shortcuts.add('delete', 'shift', Scope.MessageList, () => {
MessageUserStore.listCheckedOrSelected().length && this.deleteWithoutMoveCommand(); MessagelistUserStore.listCheckedOrSelected().length && this.deleteWithoutMoveCommand();
return false; return false;
}); });
// shortcuts.add('3', 'shift', Scope.MessageList, () => { // shortcuts.add('3', 'shift', Scope.MessageList, () => {
shortcuts.add('delete', '', Scope.MessageList, () => { shortcuts.add('delete', '', Scope.MessageList, () => {
MessageUserStore.listCheckedOrSelected().length && this.deleteCommand(); MessagelistUserStore.listCheckedOrSelected().length && this.deleteCommand();
return false; return false;
}); });
@ -728,9 +745,9 @@ export class MailMessageList extends AbstractViewRight {
}); });
shortcuts.add('t', '', [Scope.MessageList], () => { shortcuts.add('t', '', [Scope.MessageList], () => {
let message = MessageUserStore.selectorMessageSelected(); let message = MessagelistUserStore.selectedMessage();
if (!message) { if (!message) {
message = MessageUserStore.selectorMessageFocused(); message = MessagelistUserStore.focusedMessage();
} }
if (message && 0 < message.threadsLen()) { if (message && 0 < message.threadsLen()) {
@ -781,7 +798,7 @@ export class MailMessageList extends AbstractViewRight {
if (this.messageListSearchDesc()) { if (this.messageListSearchDesc()) {
this.cancelSearch(); this.cancelSearch();
return false; return false;
} else if (MessageUserStore.listEndThreadUid()) { } else if (MessagelistUserStore.endThreadUid()) {
this.cancelThreadUid(); this.cancelThreadUid();
return false; return false;
} }
@ -813,7 +830,7 @@ export class MailMessageList extends AbstractViewRight {
prefetchNextTick() { prefetchNextTick() {
if (!this.bPrefetch && !ifvisible.now() && !this.viewModelDom.hidden) { if (!this.bPrefetch && !ifvisible.now() && !this.viewModelDom.hidden) {
const message = MessageUserStore.list.find( const message = MessagelistUserStore.find(
item => item && !hasRequestedMessage(item.folder, item.uid) item => item && !hasRequestedMessage(item.folder, item.uid)
); );
if (message) { if (message) {
@ -838,7 +855,7 @@ export class MailMessageList extends AbstractViewRight {
advancedSearchClick() { advancedSearchClick() {
SettingsCapa(Capa.SearchAdv) SettingsCapa(Capa.SearchAdv)
&& showScreenPopup(AdvancedSearchPopupView, [MessageUserStore.mainMessageListSearch()]); && showScreenPopup(AdvancedSearchPopupView, [MessagelistUserStore.mainSearch()]);
} }
quotaTooltip() { quotaTooltip() {

View file

@ -42,6 +42,7 @@ import { SettingsUserStore } from 'Stores/User/Settings';
import { AccountUserStore } from 'Stores/User/Account'; import { AccountUserStore } from 'Stores/User/Account';
import { FolderUserStore } from 'Stores/User/Folder'; import { FolderUserStore } from 'Stores/User/Folder';
import { MessageUserStore } from 'Stores/User/Message'; import { MessageUserStore } from 'Stores/User/Message';
import { MessagelistUserStore } from 'Stores/User/Messagelist';
import { ThemeStore } from 'Stores/Theme'; import { ThemeStore } from 'Stores/Theme';
import * as Local from 'Storage/Client'; import * as Local from 'Storage/Client';
@ -66,10 +67,7 @@ export class MailMessageView extends AbstractViewRight {
const const
createCommandReplyHelper = type => createCommandReplyHelper = type =>
createCommand(() => { createCommand(() => this.replyOrforward(type), this.canBeRepliedOrForwarded),
this.lastReplyAction(type);
this.replyOrforward(type);
}, this.canBeRepliedOrForwarded),
createCommandActionHelper = (folderType, useFolder) => createCommandActionHelper = (folderType, useFolder) =>
createCommand(() => { createCommand(() => {
@ -101,13 +99,12 @@ export class MailMessageView extends AbstractViewRight {
this.attachmentsActions = ko.observableArray(arrayLength(attachmentsActions) ? attachmentsActions : []); this.attachmentsActions = ko.observableArray(arrayLength(attachmentsActions) ? attachmentsActions : []);
this.message = MessageUserStore.message; this.message = MessageUserStore.message;
this.hasCheckedMessages = MessageUserStore.hasCheckedMessages; this.hasCheckedMessages = MessagelistUserStore.hasCheckedMessages;
this.messageLoadingThrottle = MessageUserStore.messageLoading; this.messageLoadingThrottle = MessageUserStore.loading;
this.messagesBodiesDom = MessageUserStore.messagesBodiesDom; this.messagesBodiesDom = MessageUserStore.bodiesDom;
this.messageActiveDom = MessageUserStore.messageActiveDom; this.messageError = MessageUserStore.error;
this.messageError = MessageUserStore.messageError;
this.fullScreenMode = MessageUserStore.messageFullScreenMode; this.fullScreenMode = MessageUserStore.fullScreen;
this.messageListOfThreadsLoading = ko.observable(false).extend({ rateLimit: 1 }); this.messageListOfThreadsLoading = ko.observable(false).extend({ rateLimit: 1 });
this.highlightUnselectedAttachments = ko.observable(false).extend({ falseTimeout: 2000 }); this.highlightUnselectedAttachments = ko.observable(false).extend({ falseTimeout: 2000 });
@ -148,7 +145,7 @@ export class MailMessageView extends AbstractViewRight {
) )
}, },
messageVisibility: () => !MessageUserStore.messageLoading() && !!currentMessage(), messageVisibility: () => !MessageUserStore.loading() && !!currentMessage(),
canBeRepliedOrForwarded: () => !this.isDraftFolder() && this.messageVisibility(), canBeRepliedOrForwarded: () => !this.isDraftFolder() && this.messageVisibility(),
@ -177,7 +174,7 @@ export class MailMessageView extends AbstractViewRight {
pgpSupported: () => currentMessage() && PgpUserStore.isSupported(), pgpSupported: () => currentMessage() && PgpUserStore.isSupported(),
messageListOrViewLoading: messageListOrViewLoading:
() => MessageUserStore.listIsLoading() | MessageUserStore.messageLoading() () => MessagelistUserStore.isLoading() | MessageUserStore.loading()
}); });
this.addSubscribables({ this.addSubscribables({
@ -187,7 +184,7 @@ export class MailMessageView extends AbstractViewRight {
lastReplyAction_: value => Local.set(ClientSideKeyName.LastReplyAction, value), lastReplyAction_: value => Local.set(ClientSideKeyName.LastReplyAction, value),
message: message => { message: message => {
this.messageActiveDom(null); MessageUserStore.activeDom(null);
if (message) { if (message) {
this.showAttachmentControls(false); this.showAttachmentControls(false);
@ -206,7 +203,7 @@ export class MailMessageView extends AbstractViewRight {
this.viewFromDkimData(message.fromDkimData()); this.viewFromDkimData(message.fromDkimData());
this.viewToShort(message.toToLine(true, true)); this.viewToShort(message.toToLine(true, true));
} else { } else {
MessageUserStore.selectorMessageSelected(null); MessagelistUserStore.selectedMessage(null);
this.viewHash = ''; this.viewHash = '';
@ -272,6 +269,7 @@ export class MailMessageView extends AbstractViewRight {
* @returns {void} * @returns {void}
*/ */
replyOrforward(sType) { replyOrforward(sType) {
this.lastReplyAction(sType);
showMessageComposer([sType, currentMessage()]); showMessageComposer([sType, currentMessage()]);
} }
@ -323,7 +321,7 @@ export class MailMessageView extends AbstractViewRight {
if (eqs(event, '.messageItemHeader .subjectParent .flagParent')) { if (eqs(event, '.messageItemHeader .subjectParent .flagParent')) {
const message = currentMessage(); const message = currentMessage();
message && rl.app.messageListAction( message && MessagelistUserStore.setAction(
message.folder, message.folder,
message.isFlagged() ? MessageSetAction.UnsetFlag : MessageSetAction.SetFlag, message.isFlagged() ? MessageSetAction.UnsetFlag : MessageSetAction.SetFlag,
[message] [message]
@ -551,7 +549,7 @@ export class MailMessageView extends AbstractViewRight {
* @returns {string} * @returns {string}
*/ */
printableCheckedMessageCount() { printableCheckedMessageCount() {
const cnt = MessageUserStore.listCheckedOrSelectedUidsWithSubMails().length; const cnt = MessagelistUserStore.listCheckedOrSelectedUidsWithSubMails().length;
return 0 < cnt ? (100 > cnt ? cnt : '99+') : ''; return 0 < cnt ? (100 > cnt ? cnt : '99+') : '';
} }
@ -575,7 +573,7 @@ export class MailMessageView extends AbstractViewRight {
MessageFlagsCache.store(oMessage); MessageFlagsCache.store(oMessage);
MessageUserStore.reloadFlagsAndCachedMessage(); MessagelistUserStore.reloadFlagsAndCachedMessage();
} }
} }

View file

@ -72,12 +72,12 @@ export class SystemDropDownUserView extends AbstractViewRight {
// MessageUserStore.setMessage(); // MessageUserStore.setMessage();
// MessageUserStore.purgeMessageBodyCache(); // MessageUserStore.purgeMessageBodyCache();
// MessageUserStore.hideMessageBodies(); // MessageUserStore.hideMessageBodies();
MessageUserStore.list([]); MessagelistUserStore([]);
// FolderUserStore.folderList([]); // FolderUserStore.folderList([]);
Remote.foldersReload(value => { loadFolders(value => {
if (value) { if (value) {
// 4. Change to INBOX = reload MessageList // 4. Change to INBOX = reload MessageList
// MessageUserStore.setMessageList(); // MessagelistUserStore.setMessageList();
} }
}); });
AccountUserStore.loading(false); AccountUserStore.loading(false);
@ -126,7 +126,7 @@ export class SystemDropDownUserView extends AbstractViewRight {
onBuild() { onBuild() {
shortcuts.add('m,contextmenu', '', [Scope.MessageList, Scope.MessageView, Scope.Settings], () => { shortcuts.add('m,contextmenu', '', [Scope.MessageList, Scope.MessageView, Scope.Settings], () => {
if (!this.viewModelDom.hidden) { if (!this.viewModelDom.hidden) {
MessageUserStore.messageFullScreenMode(false); MessageUserStore.fullScreen(false);
this.accountMenuDropdownTrigger(true); this.accountMenuDropdownTrigger(true);
return false; return false;
} }