Cleanup calls to Knockout observableArray

Improved Knockout observableArray
This commit is contained in:
djmaze 2021-01-22 12:23:20 +01:00
parent fa5476e486
commit b6f0b634fb
47 changed files with 251 additions and 276 deletions

View file

@ -69,7 +69,7 @@ class AdminApp extends AbstractApp {
let list = [];
const loading = {};
PackageStore.packages().forEach(item => {
PackageStore.packages.forEach(item => {
if (item && item.loading()) {
loading[item.file] = item;
}

View file

@ -122,7 +122,7 @@ class AppUser extends AbstractApp {
}
reloadFlagsCurrentMessageListAndMessageFromCache() {
MessageStore.messageList().forEach(message =>
MessageStore.messageList.forEach(message =>
MessageFlagsCache.initMessage(message)
);
MessageFlagsCache.initMessage(MessageStore.message());
@ -271,7 +271,7 @@ class AppUser extends AbstractApp {
}
}
this.reloadMessageList(!MessageStore.messageList().length);
this.reloadMessageList(!MessageStore.messageList.length);
this.quotaDebounce();
}
}
@ -479,9 +479,9 @@ class AppUser extends AbstractApp {
let parentEmail = Settings.get('ParentEmail') || sAccountEmail;
if (Array.isArray(oData.Result.Accounts)) {
AccountStore.accounts().forEach(oAccount => {
counts[oAccount.email] = oAccount.count();
});
AccountStore.accounts.forEach(oAccount =>
counts[oAccount.email] = oAccount.count()
);
delegateRunOnDestroy(AccountStore.accounts());
@ -673,13 +673,10 @@ class AppUser extends AbstractApp {
if (folder.fullNameRaw === FolderStore.currentFolderFullNameRaw()) {
this.reloadMessageList();
}
} else if (unreadCountChange) {
if (folder.fullNameRaw === FolderStore.currentFolderFullNameRaw()) {
const list = MessageStore.messageList();
if (Array.isNotEmpty(list)) {
this.folderInformation(folder.fullNameRaw, list);
}
}
} else if (unreadCountChange
&& folder.fullNameRaw === FolderStore.currentFolderFullNameRaw()
&& MessageStore.messageList.length) {
this.folderInformation(folder.fullNameRaw, MessageStore.messageList());
}
}
});

View file

@ -210,8 +210,8 @@ export class MessageFlagsCache
}
}
if (message.threads().length) {
const unseenSubUid = message.threads().find(sSubUid => {
if (message.threads.length) {
const unseenSubUid = message.threads.find(sSubUid => {
if (uid !== sSubUid) {
const subFlags = this.getFor(message.folder, sSubUid);
return subFlags && subFlags.length && !!subFlags[0];
@ -219,7 +219,7 @@ export class MessageFlagsCache
return false;
});
const flaggedSubUid = message.threads().find(sSubUid => {
const flaggedSubUid = message.threads.find(sSubUid => {
if (uid !== sSubUid) {
const subFlags = this.getFor(message.folder, sSubUid);
return subFlags && subFlags.length && !!subFlags[1];

View file

@ -42,7 +42,7 @@ class Selector {
) {
this.list = koList;
this.listChecked = ko.computed(() => this.list().filter(item => item.checked())).extend({ rateLimit: 0 });
this.listChecked = ko.computed(() => this.list.filter(item => item.checked())).extend({ rateLimit: 0 });
this.isListChecked = ko.computed(() => 0 < this.listChecked().length);
this.focusedItem = koFocusedItem || ko.observable(null);
@ -329,11 +329,11 @@ class Selector {
result = null;
const pageStep = 10,
list = this.list(),
listLen = list ? list.length : 0,
list = this.list,
listLen = list.length,
focused = this.focusedItem();
if (0 < listLen) {
if (listLen) {
if (focused) {
if (isArrow) {
let i = list.indexOf(focused);

View file

@ -326,7 +326,7 @@ export function folderListOptionsBuilder(
}
}
if (oItem.subscribed() && oItem.subFolders().length) {
if (oItem.subscribed() && oItem.subFolders.length) {
aResult = aResult.concat(
folderListOptionsBuilder(
[],

View file

@ -11,7 +11,7 @@ export class AbstractScreen {
/**
* @returns {Array}
*/
viewModels() {
get viewModels() {
return this.aViewModels;
}

View file

@ -263,8 +263,8 @@ function screenOnRoute(screenName, subPart) {
if (!vmScreen.__builded) {
vmScreen.__builded = true;
if (isNonEmptyArray(vmScreen.viewModels())) {
vmScreen.viewModels().forEach(ViewModelClass => {
if (vmScreen.viewModels.length) {
vmScreen.viewModels.forEach(ViewModelClass => {
buildViewModel(ViewModelClass, vmScreen);
});
}
@ -278,8 +278,8 @@ function screenOnRoute(screenName, subPart) {
currentScreen.onHide && currentScreen.onHide();
currentScreen.onHideWithDelay && setTimeout(()=>currentScreen.onHideWithDelay(), 500);
if (isNonEmptyArray(currentScreen.viewModels())) {
currentScreen.viewModels().forEach(ViewModelClass => {
if (isNonEmptyArray(currentScreen.viewModels)) {
currentScreen.viewModels.forEach(ViewModelClass => {
if (
ViewModelClass.__vm &&
ViewModelClass.__dom &&
@ -302,8 +302,8 @@ function screenOnRoute(screenName, subPart) {
if (currentScreen && !isSameScreen) {
currentScreen.onShow && currentScreen.onShow();
if (isNonEmptyArray(currentScreen.viewModels())) {
currentScreen.viewModels().forEach(ViewModelClass => {
if (isNonEmptyArray(currentScreen.viewModels)) {
currentScreen.viewModels.forEach(ViewModelClass => {
if (
ViewModelClass.__vm &&
ViewModelClass.__dom &&

View file

@ -46,7 +46,7 @@ class FilterModel extends AbstractModel {
actionType: FiltersAction.MoveTo
});
this.conditions = ko.observableArray([]);
this.conditions = ko.observableArray();
const fGetRealFolderName = (folderFullNameRaw) => {
const folder = getFolderFromCacheList(folderFullNameRaw);
@ -137,7 +137,7 @@ class FilterModel extends AbstractModel {
return false;
}
if (this.conditions().length && this.conditions().find(cond => cond && !cond.verify())) {
if (this.conditions.length && this.conditions.find(cond => cond && !cond.verify())) {
return false;
}
@ -180,7 +180,7 @@ class FilterModel extends AbstractModel {
ID: this.id,
Enabled: this.enabled() ? '1' : '0',
Name: this.name(),
Conditions: this.conditions().map(item => item.toJson()),
Conditions: this.conditions.map(item => item.toJson()),
ConditionsType: this.conditionsType(),
ActionType: this.actionType(),
@ -259,7 +259,7 @@ class FilterModel extends AbstractModel {
filter.actionKeep(this.actionKeep());
filter.actionNoStop(this.actionNoStop());
filter.conditions(this.conditions().map(item => item.cloneSelf()));
filter.conditions(this.conditions.map(item => item.cloneSelf()));
return filter;
}

View file

@ -85,7 +85,7 @@ class FolderModel extends AbstractModel {
hasSubscribedSubfolders:
() =>
!!folder.subFolders().find(
!!folder.subFolders.find(
oFolder => (oFolder.subscribed() || oFolder.hasSubscribedSubfolders()) && !oFolder.isSystemFolder()
),
@ -129,7 +129,7 @@ class FolderModel extends AbstractModel {
return '';
},
canBeDeleted: () => !folder.isSystemFolder() && !folder.subFolders().length,
canBeDeleted: () => !folder.isSystemFolder() && !folder.subFolders.length,
selectableForFolderList: () => !folder.isSystemFolder() && folder.selectable,
@ -218,7 +218,7 @@ class FolderModel extends AbstractModel {
hasUnreadMessages: () => 0 < folder.messageCountUnread() && folder.printableUnreadCount(),
hasSubscribedUnreadMessagesSubfolders: () =>
!!folder.subFolders().find(
!!folder.subFolders.find(
folder => folder.hasUnreadMessages() || folder.hasSubscribedUnreadMessagesSubfolders()
)
});

View file

@ -72,12 +72,12 @@ class MessageModel extends AbstractModel {
});
this.attachments = ko.observableArray(new AttachmentCollectionModel);
this.attachmentsSpecData = ko.observableArray([]);
this.threads = ko.observableArray([]);
this.attachmentsSpecData = ko.observableArray();
this.threads = ko.observableArray();
this.addComputables({
attachmentIconClass: () => File.getCombinedIconClass(this.hasAttachments() ? this.attachmentsSpecData() : []),
threadsLen: () => this.threads().length,
threadsLen: () => this.threads.length,
isImportant: () => MessagePriority.High === this.priority(),
});
}
@ -502,7 +502,7 @@ class MessageModel extends AbstractModel {
el.src = attachment.linkPreview();
}
} else if (data.xSrcLocation) {
const attachment = this.attachments().find(item => data.xSrcLocation === item.contentLocation)
const attachment = this.attachments.find(item => data.xSrcLocation === item.contentLocation)
|| findAttachmentByCid(data.xSrcLocation);
if (attachment && attachment.download) {
el.loading = 'lazy';

View file

@ -274,7 +274,7 @@ class SieveScriptModel extends AbstractModel
hasChanges: false
});
this.filters = ko.observableArray([]);
this.filters = ko.observableArray();
// this.saving = ko.observable(false).extend({ throttle: 200 });
this.addSubscribables({
@ -296,7 +296,7 @@ class SieveScriptModel extends AbstractModel
verify() {
this.nameError(!this.name().trim());
this.bodyError(this.allowFilters() ? !this.filters().length : !this.body().trim());
this.bodyError(this.allowFilters() ? !this.filters.length : !this.body().trim());
return !this.nameError() && !this.bodyError();
}
@ -305,7 +305,7 @@ class SieveScriptModel extends AbstractModel
name: this.name(),
active: this.active() ? '1' : '0',
body: this.body(),
filters: this.filters().map(item => item.toJson())
filters: this.filters.map(item => item.toJson())
};
}

View file

@ -446,8 +446,8 @@ class RemoteUserFetch extends AbstractFetchRemote {
uids.push(messageListItem.uid);
}
if (messageListItem.threads().length) {
messageListItem.threads().forEach(uid => {
if (messageListItem.threads.length) {
messageListItem.threads.forEach(uid => {
if (!MessageFlagsCache.getFor(messageListItem.folder, uid)) {
uids.push(uid);
}

View file

@ -13,7 +13,7 @@ class AbstractSettingsScreen extends AbstractScreen {
constructor(viewModels) {
super('settings', viewModels);
this.menu = ko.observableArray([]);
this.menu = ko.observableArray();
this.oCurrentSubScreen = null;
@ -113,7 +113,7 @@ class AbstractSettingsScreen extends AbstractScreen {
o.oCurrentSubScreen.viewModelDom.hidden = false;
o.oCurrentSubScreen.onShow && o.oCurrentSubScreen.onShow();
o.menu().forEach(item => {
o.menu.forEach(item => {
item.selected(
settingsScreen &&
settingsScreen.__rlSettingsData &&

View file

@ -106,7 +106,7 @@ class MailBoxUserScreen extends AbstractScreen {
FolderStore.foldersInboxUnreadCount(e.detail);
const email = AccountStore.email();
AccountStore.accounts().forEach(item => {
AccountStore.accounts.forEach(item => {
if (item && email === item.email) {
item.count(e.detail);
}

View file

@ -67,7 +67,7 @@ class GeneralAdminSettings {
: '';
this.themesOptions = ko.computed(() =>
this.themes().map(theme => ({ optValue: theme, optText: convertThemeName(theme) }))
this.themes.map(theme => ({ optValue: theme, optText: convertThemeName(theme) }))
);
this.languageFullName = ko.computed(() => convertLangName(this.language()));

View file

@ -15,13 +15,13 @@ class PackagesAdminSettings {
this.packagesMainUpdatable = PackageStore.packagesMainUpdatable;
this.packagesCurrent = ko.computed(() =>
this.packages().filter(item => item && item.installed && !item.compare)
this.packages.filter(item => item && item.installed && !item.compare)
);
this.packagesAvailableForUpdate = ko.computed(() =>
this.packages().filter(item => item && item.installed && !!item.compare)
this.packages.filter(item => item && item.installed && !!item.compare)
);
this.packagesAvailableForInstallation = ko.computed(() =>
this.packages().filter(item => item && !item.installed)
this.packages.filter(item => item && !item.installed)
);
this.visibility = ko.computed(() => (PackageStore.packages.loading() ? 'visible' : 'hidden'));
@ -47,7 +47,7 @@ class PackagesAdminSettings {
}
}
this.packages().forEach(item => {
this.packages.forEach(item => {
if (item && packageToRequest && item.loading && item.loading() && packageToRequest.file === item.file) {
packageToRequest.loading(false);
item.loading(false);

View file

@ -91,7 +91,7 @@ class FiltersUserSettings {
Remote.filtersScriptActivate(
(result, data) => {
if (StorageResultType.Success === result && data && data.Result) {
this.scripts().forEach(script => script.active(script.name() === name));
this.scripts.forEach(script => script.active(script.name() === name));
} else {
this.setError((data && data.ErrorCode)
? (data.ErrorMessageAdditional || getNotification(data.ErrorCode))

View file

@ -43,7 +43,7 @@ class OpenPgpUserSettings {
this.openPgpKeyForDeletion(null);
if (openPgpKeyToRemove && PgpStore.openpgpKeyring) {
const findedItem = PgpStore.openpgpkeys().find(key => openPgpKeyToRemove === key);
const findedItem = PgpStore.openpgpkeys.find(key => openPgpKeyToRemove === key);
if (findedItem) {
PgpStore.openpgpkeys.remove(findedItem);
delegateRunOnDestroy(findedItem);

View file

@ -13,7 +13,7 @@ class ThemesUserSettings {
constructor() {
this.theme = ThemeStore.theme;
this.themes = ThemeStore.themes;
this.themesObjects = ko.observableArray([]);
this.themesObjects = ko.observableArray();
this.background = {};
this.background.name = ThemeStore.themeBackgroundName;
@ -27,7 +27,7 @@ class ThemesUserSettings {
this.themeTrigger = ko.observable(SaveSettingsStep.Idle).extend({ throttle: 100 });
this.theme.subscribe((value) => {
this.themesObjects().forEach(theme => {
this.themesObjects.forEach(theme => {
theme.selected(value === theme.name);
});
@ -54,7 +54,7 @@ class ThemesUserSettings {
const currentTheme = this.theme();
this.themesObjects(
this.themes().map(theme => ({
this.themes.map(theme => ({
name: theme,
nameDisplay: convertThemeName(theme),
selected: ko.observable(theme === currentTheme),

View file

@ -2,9 +2,9 @@ import ko from 'ko';
class DomainAdminStore {
constructor() {
this.domains = ko.observableArray([]);
this.domains = ko.observableArray();
this.domains.loading = ko.observable(false).extend({ 'throttle': 100 });
this.domainsWithoutAliases = ko.computed(() => this.domains().filter(item => item && !item.alias));
this.domainsWithoutAliases = ko.computed(() => this.domains.filter(item => item && !item.alias));
}
}

View file

@ -2,7 +2,7 @@ import ko from 'ko';
class PackageAdminStore {
constructor() {
this.packages = ko.observableArray([]);
this.packages = ko.observableArray();
this.packages.loading = ko.observable(false).extend({ throttle: 100 });
ko.addObservablesTo(this, {

View file

@ -2,7 +2,7 @@ import ko from 'ko';
class PluginAdminStore {
constructor() {
this.plugins = ko.observableArray([]);
this.plugins = ko.observableArray();
this.plugins.loading = ko.observable(false).extend({ throttle: 100 });
this.plugins.error = ko.observable('');
}

View file

@ -2,8 +2,8 @@ import ko from 'ko';
class LanguageStore {
constructor() {
this.languages = ko.observableArray([]);
this.languagesAdmin = ko.observableArray([]);
this.languages = ko.observableArray();
this.languagesAdmin = ko.observableArray();
this.language = ko
.observable('')

View file

@ -2,7 +2,7 @@ import ko from 'ko';
class ThemeStore {
constructor() {
this.themes = ko.observableArray([]);
this.themes = ko.observableArray();
this.themeBackgroundName = ko.observable('');
this.themeBackgroundHash = ko.observable('');

View file

@ -8,10 +8,10 @@ class AccountUserStore {
signature: ''
});
this.accounts = ko.observableArray([]);
this.accounts = ko.observableArray();
this.accounts.loading = ko.observable(false).extend({ throttle: 100 });
this.getEmailAddresses = () => this.accounts().map(item => item ? item.email : null).filter(v => v);
this.getEmailAddresses = () => this.accounts.map(item => item ? item.email : null).filter(v => v);
this.accountsUnreadCount = ko.computed(() => 0);
// this.accountsUnreadCount = ko.computed(() => {

View file

@ -50,7 +50,7 @@ class AppUserStore {
}
});
this.attachmentsActions = ko.observableArray([]);
this.attachmentsActions = ko.observableArray();
this.devEmail = '';
this.devPassword = '';

View file

@ -2,7 +2,7 @@ import ko from 'ko';
class ContactUserStore {
constructor() {
this.contacts = ko.observableArray([]);
this.contacts = ko.observableArray();
this.contacts.loading = ko.observable(false).extend({ throttle: 200 });
this.contacts.importing = ko.observable(false).extend({ throttle: 200 });
this.contacts.syncing = ko.observable(false).extend({ throttle: 200 });

View file

@ -36,7 +36,7 @@ class FolderUserStore {
this.namespace = '';
this.folderList = ko.observableArray([]);
this.folderList = ko.observableArray();
this.currentFolder = ko.observable(null).extend({ toggleSubscribeProperty: [this, 'selected'] });
@ -47,7 +47,7 @@ class FolderUserStore {
);
this.foldersListWithSingleInboxRootFolder = ko.computed(
() => !this.folderList().find(folder => folder && !folder.isSystemFolder() && folder.visible())
() => !this.folderList.find(folder => folder && !folder.isSystemFolder() && folder.visible())
);
this.currentFolderFullNameRaw = ko.computed(() => (this.currentFolder() ? this.currentFolder().fullNameRaw : ''));
@ -66,14 +66,13 @@ class FolderUserStore {
this.folderListSystemNames = ko.computed(() => {
const list = [getFolderInboxName()],
folders = this.folderList(),
sentFolder = this.sentFolder(),
draftFolder = this.draftFolder(),
spamFolder = this.spamFolder(),
trashFolder = this.trashFolder(),
archiveFolder = this.archiveFolder();
if (Array.isNotEmpty(folders)) {
if (this.folderList.length) {
if (sentFolder && UNUSED_OPTION_VALUE !== sentFolder) {
list.push(sentFolder);
}
@ -178,7 +177,7 @@ class FolderUserStore {
timeouts.push([folder.interval, folder.fullNameRaw]);
}
if (folder && folder.subFolders().length) {
if (folder && folder.subFolders.length) {
fSearchFunction(folder.subFolders());
}
});

View file

@ -2,10 +2,10 @@ import ko from 'ko';
class IdentityUserStore {
constructor() {
this.identities = ko.observableArray([]);
this.identities = ko.observableArray();
this.identities.loading = ko.observable(false).extend({ throttle: 100 });
this.getIDS = () => this.identities().map(item => (item ? item.id() : null)).filter(value => null !== value);
this.getIDS = () => this.identities.map(item => (item ? item.id() : null)).filter(value => null !== value);
}
}

View file

@ -57,7 +57,7 @@ class MessageUserStore {
constructor() {
this.staticMessage = new MessageModel();
this.messageList = ko.observableArray([]).extend({ rateLimit: 0 });
this.messageList = ko.observableArray().extend({ rateLimit: 0 });
ko.addObservablesTo(this, {
messageListCount: 0,
@ -136,7 +136,7 @@ class MessageUserStore {
this.isMessageSelected = ko.computed(() => null !== this.message());
this.messageListChecked = ko
.computed(() => this.messageList().filter(item => item.checked()))
.computed(() => this.messageList.filter(item => item.checked()))
.extend({ rateLimit: 0 });
this.hasCheckedMessages = ko.computed(() => 0 < this.messageListChecked().length).extend({ rateLimit: 0 });
@ -279,7 +279,7 @@ class MessageUserStore {
uidForRemove = uidForRemove.map(mValue => pInt(mValue));
let unseenCount = 0,
messageList = this.messageList(),
messageList = this.messageList,
currentMessage = this.message();
const trashFolder = FolderStore.trashFolder(),
@ -342,7 +342,7 @@ class MessageUserStore {
setTimeout(() => {
messages.forEach(item => {
this.messageList.remove(item);
messageList.remove(item);
});
}, 350);
}
@ -357,10 +357,7 @@ class MessageUserStore {
}
if (this.messageListThreadUid()) {
messageList = this.messageList();
if (
messageList &&
messageList.length &&
!!messageList.find(item => !!(item && item.deleted() && item.uid === this.messageListThreadUid()))
) {
@ -592,11 +589,11 @@ class MessageUserStore {
(message.folder !== selectedMessage.folder || message.uid !== selectedMessage.uid)
) {
this.selectorMessageSelected(null);
if (1 === this.messageList().length) {
if (1 === this.messageList.length) {
this.selectorMessageFocused(null);
}
} else if (!selectedMessage && message) {
selectedMessage = this.messageList().find(
selectedMessage = this.messageList.find(
subMessage =>
subMessage &&
subMessage.folder === message.folder &&

View file

@ -135,11 +135,11 @@ class PgpUserStore {
this.openpgp = null;
this.openpgpkeys = ko.observableArray([]);
this.openpgpkeys = ko.observableArray();
this.openpgpKeyring = null;
this.openpgpkeysPublic = ko.computed(() => this.openpgpkeys().filter(item => item && !item.isPrivate));
this.openpgpkeysPrivate = ko.computed(() => this.openpgpkeys().filter(item => item && item.isPrivate));
this.openpgpkeysPublic = ko.computed(() => this.openpgpkeys.filter(item => item && !item.isPrivate));
this.openpgpkeysPrivate = ko.computed(() => this.openpgpkeys.filter(item => item && item.isPrivate));
}
/**

View file

@ -3,9 +3,9 @@ import ko from 'ko';
class SieveUserStore {
constructor() {
// capabilities
this.capa = ko.observableArray([]);
this.capa = ko.observableArray();
// Sieve scripts SieveScriptModel
this.scripts = ko.observableArray([]);
this.scripts = ko.observableArray();
}
}

View file

@ -4,10 +4,10 @@ import ko from 'ko';
class TemplateUserStore {
constructor() {
this.templates = ko.observableArray([]);
this.templates = ko.observableArray();
this.templates.loading = ko.observable(false).extend({ throttle: 100 });
this.templatesNames = ko.observableArray([]).extend({ throttle: 1000 });
this.templatesNames = ko.observableArray().extend({ throttle: 1000 });
this.templatesNames.skipFirst = true;
this.subscribers();

View file

@ -208,7 +208,7 @@ class ComposePopupView extends AbstractViewNext {
}
}).extend({ notify: 'always' });
this.attachments = ko.observableArray([]);
this.attachments = ko.observableArray();
this.dragAndDropOver = ko.observable(false).extend({ throttle: 1 });
this.dragAndDropVisible = ko.observable(false).extend({ throttle: 1 });
@ -256,17 +256,17 @@ class ComposePopupView extends AbstractViewNext {
return result;
},
attachmentsInProcess: () => this.attachments().filter(item => item && !item.complete()),
attachmentsInReady: () => this.attachments().filter(item => item && item.complete()),
attachmentsInError: () => this.attachments().filter(item => item && item.error()),
attachmentsInProcess: () => this.attachments.filter(item => item && !item.complete()),
attachmentsInReady: () => this.attachments.filter(item => item && item.complete()),
attachmentsInError: () => this.attachments.filter(item => item && item.error()),
attachmentsCount: () => this.attachments().length,
attachmentsInErrorCount: () => this.attachmentsInError().length,
attachmentsInProcessCount: () => this.attachmentsInProcess().length,
attachmentsCount: () => this.attachments.length,
attachmentsInErrorCount: () => this.attachmentsInError.length,
attachmentsInProcessCount: () => this.attachmentsInProcess.length,
isDraftFolderMessage: () => this.draftFolder() && this.draftUid(),
identitiesOptions: () =>
IdentityStore.identities().map(item => ({
IdentityStore.identities.map(item => ({
'item': item,
'optValue': item.id(),
'optText': item.formattedName()
@ -1106,7 +1106,7 @@ class ComposePopupView extends AbstractViewNext {
}
});
} else {
this.attachments().forEach(attachment => {
this.attachments.forEach(attachment => {
if (attachment && attachment.fromMessage) {
attachment
.waiting(false)
@ -1221,7 +1221,7 @@ class ComposePopupView extends AbstractViewNext {
* @returns {?Object}
*/
getAttachmentById(id) {
return this.attachments().find(item => item && id === item.id);
return this.attachments.find(item => item && id === item.id);
}
cancelAttachmentHelper(id, oJua) {
@ -1428,7 +1428,7 @@ class ComposePopupView extends AbstractViewNext {
if (ComposeType.ForwardAsAttachment === type) {
this.addMessageAsAttachment(message);
} else {
message.attachments().forEach(item => {
message.attachments.forEach(item => {
let add = false;
switch (type) {
case ComposeType.Reply:
@ -1464,15 +1464,15 @@ class ComposePopupView extends AbstractViewNext {
*/
isEmptyForm(includeAttachmentInProgress = true) {
const withoutAttachment = includeAttachmentInProgress
? !this.attachments().length
? !this.attachments.length
: !this.attachmentsInReady().length;
return (
!this.to().length &&
!this.cc().length &&
!this.bcc().length &&
!this.replyTo().length &&
!this.subject().length &&
!this.to.length &&
!this.cc.length &&
!this.bcc.length &&
!this.replyTo.length &&
!this.subject.length &&
withoutAttachment &&
(!this.oEditor || !this.oEditor.getData())
);
@ -1528,7 +1528,7 @@ class ComposePopupView extends AbstractViewNext {
* @returns {Array}
*/
getAttachmentsDownloadsForUpload() {
return this.attachments().filter(item => item && !item.tempName()).map(
return this.attachments.filter(item => item && !item.tempName()).map(
item => item.id
);
}

View file

@ -41,10 +41,10 @@ class ComposeOpenPgpPopupView extends AbstractViewNext {
submitRequest: false
});
this.encryptKeys = ko.observableArray([]);
this.encryptKeys = ko.observableArray();
this.addComputables({
encryptKeysView: () => this.encryptKeys().map(oKey => (oKey ? oKey.key : null)).filter(v => v),
encryptKeysView: () => this.encryptKeys.map(oKey => (oKey ? oKey.key : null)).filter(v => v),
privateKeysOptions: () => {
const opts = PgpStore.openpgpkeysPrivate().map((oKey, iIndex) => {
@ -150,13 +150,10 @@ class ComposeOpenPgpPopupView extends AbstractViewNext {
}
if (result && this.encrypt()) {
if (!this.encryptKeys().length) {
this.notification(i18n('PGP_NOTIFICATIONS/NO_PUBLIC_KEYS_FOUND'));
result = false;
} else if (this.encryptKeys()) {
if (this.encryptKeys.length) {
aPublicKeys = [];
this.encryptKeys().forEach(oKey => {
this.encryptKeys.forEach(oKey => {
if (oKey && oKey.key) {
aPublicKeys = aPublicKeys.concat(oKey.key.getNativeKeys().flat(Infinity).filter(v => v));
} else if (oKey && oKey.email) {
@ -170,9 +167,12 @@ class ComposeOpenPgpPopupView extends AbstractViewNext {
}
});
if (result && (!aPublicKeys.length || this.encryptKeys().length !== aPublicKeys.length)) {
if (result && (!aPublicKeys.length || this.encryptKeys.length !== aPublicKeys.length)) {
result = false;
}
} else {
this.notification(i18n('PGP_NOTIFICATIONS/NO_PUBLIC_KEYS_FOUND'));
result = false;
}
}
@ -261,11 +261,10 @@ class ComposeOpenPgpPopupView extends AbstractViewNext {
@command()
addCommand() {
const keyId = this.selectedPublicKey(),
keys = this.encryptKeys(),
option = keyId ? this.publicKeysOptions().find(item => item && keyId === item.id) : null;
if (option) {
keys.push({
this.encryptKeys.push({
'empty': !option.key,
'selected': ko.observable(!!option.key),
'removable': ko.observable(!this.sign() || !this.signKey() || this.signKey().key.id !== option.key.id),
@ -273,16 +272,14 @@ class ComposeOpenPgpPopupView extends AbstractViewNext {
'hash': option.key.id.substr(KEY_NAME_SUBSTR).toUpperCase(),
'key': option.key
});
this.encryptKeys(keys);
}
}
@command()
updateCommand() {
this.encryptKeys().forEach(oKey => {
oKey.removable(!this.sign() || !this.signKey() || this.signKey().key.id !== oKey.key.id);
});
this.encryptKeys.forEach(oKey =>
oKey.removable(!this.sign() || !this.signKey() || this.signKey().key.id !== oKey.key.id)
);
}
deletePublickKey(publicKey) {
@ -390,7 +387,7 @@ class ComposeOpenPgpPopupView extends AbstractViewNext {
}).flat().validUnique(encryptKey => encryptKey.hash)
);
if (this.encryptKeys().length) {
if (this.encryptKeys.length) {
this.encrypt(true);
}
}

View file

@ -73,7 +73,7 @@ class ContactsPopupView extends AbstractViewNext {
this.contacts = ContactStore.contacts;
this.viewProperties = ko.observableArray([]);
this.viewProperties = ko.observableArray();
/*
// Somehow this is broken now when calling addNewProperty
@ -127,17 +127,17 @@ class ContactsPopupView extends AbstractViewNext {
contactsPaginator: computedPaginatorHelper(this.contactsPage, pagecount),
viewPropertiesNames: () => this.viewProperties().filter(propertyIsName),
viewPropertiesNames: () => this.viewProperties.filter(propertyIsName),
viewPropertiesEmails: () => this.viewProperties().filter(propertyIsMail),
viewPropertiesEmails: () => this.viewProperties.filter(propertyIsMail),
viewPropertiesOther: () => this.viewProperties().filter(property => property.isType(ContactPropertyType.Nick)),
viewPropertiesOther: () => this.viewProperties.filter(property => property.isType(ContactPropertyType.Nick)),
viewPropertiesWeb: () => this.viewProperties().filter(property => property.isType(ContactPropertyType.Web)),
viewPropertiesWeb: () => this.viewProperties.filter(property => property.isType(ContactPropertyType.Web)),
viewPropertiesPhones: () => this.viewProperties().filter(property => property.isType(ContactPropertyType.Phone)),
viewPropertiesPhones: () => this.viewProperties.filter(property => property.isType(ContactPropertyType.Phone)),
contactHasValidName: () => !!this.viewProperties().find(prop => propertyIsName(prop) && prop.isValid()),
contactHasValidName: () => !!this.viewProperties.find(prop => propertyIsName(prop) && prop.isValid()),
/*
viewPropertiesEmailsEmptyAndOnFocused: () => this.viewPropertiesEmails().filter(propertyFocused),
viewPropertiesPhonesEmptyAndOnFocused: () => this.viewPropertiesPhones().filter(propertyFocused),
@ -145,7 +145,7 @@ class ContactsPopupView extends AbstractViewNext {
viewPropertiesOtherEmptyAndOnFocused: () => this.viewPropertiesOther().filter(propertyFocused),
*/
contactsCheckedOrSelected: () => {
const checked = this.contacts().filter(item => item.checked && item.checked()),
const checked = this.contacts.filter(item => item.checked && item.checked()),
selected = this.currentContact();
return selected
@ -155,7 +155,7 @@ class ContactsPopupView extends AbstractViewNext {
contactsCheckedOrSelectedUids: () => this.contactsCheckedOrSelected().map(contact => contact.id),
viewHash: () => '' + this.viewProperties().map(property => property.value && property.value()).join('')
viewHash: () => '' + this.viewProperties.map(property => property.value && property.value()).join('')
});
this.search.subscribe(() => this.reloadContactList());
@ -243,7 +243,7 @@ class ContactsPopupView extends AbstractViewNext {
@command(self =>
!self.viewSaving() && !self.viewReadOnly()
&& (self.contactHasValidName() || self.viewProperties().find(prop => propertyIsMail(prop) && prop.isValid()))
&& (self.contactHasValidName() || self.viewProperties.find(prop => propertyIsMail(prop) && prop.isValid()))
)
saveCommand() {
this.viewSaving(true);
@ -282,7 +282,7 @@ class ContactsPopupView extends AbstractViewNext {
},
requestUid,
this.viewID(),
this.viewProperties().map(oItem => oItem.toJSON())
this.viewProperties.map(oItem => oItem.toJSON())
);
}
@ -322,7 +322,7 @@ class ContactsPopupView extends AbstractViewNext {
}
addNewOrFocusProperty(type, typeStr) {
const item = this.viewProperties().find(prop => prop.isType(type));
const item = this.viewProperties.find(prop => prop.isType(type));
if (item) {
item.focused(true);
} else {
@ -393,7 +393,7 @@ class ContactsPopupView extends AbstractViewNext {
contacts = this.contactsCheckedOrSelected();
let currentContact = this.currentContact(),
count = this.contacts().length;
count = this.contacts.length;
if (contacts.length) {
contacts.forEach(contact => {

View file

@ -33,7 +33,7 @@ class FilterPopupView extends AbstractViewNext {
this.selectedFolderValue.subscribe(() => this.filter() && this.filter().actionValueError(false));
['actionTypeOptions','fieldOptions','typeOptions','typeOptionsSize','typeOptionsBody'].forEach(
key => this[key] = ko.observableArray([])
key => this[key] = ko.observableArray()
);
initOnStartOrLangChange(this.populateOptions.bind(this));
@ -80,7 +80,7 @@ class FilterPopupView extends AbstractViewNext {
// this.actionTypeOptions.push({'id': FiltersAction.None,
// 'name': i18n('GLOBAL/NONE')});
const modules = SieveStore.capa();
const modules = SieveStore.capa;
if (modules) {
if (modules.includes('imap4flags')) {
this.allowMarkAsRead(true);

View file

@ -17,11 +17,11 @@ class LanguagesPopupView extends AbstractViewNext {
this.fLang = null;
this.userLanguage = ko.observable('');
this.langs = ko.observableArray([]);
this.langs = ko.observableArray();
this.languages = ko.computed(() => {
const userLanguage = this.userLanguage();
return this.langs().map(language => ({
return this.langs.map(language => ({
key: language,
user: language === userLanguage,
selected: ko.observable(false),
@ -39,9 +39,7 @@ class LanguagesPopupView extends AbstractViewNext {
setLanguageSelection() {
const currentLang = this.fLang ? ko.unwrap(this.fLang) : '';
this.languages().forEach(item => {
item.selected(item.key === currentLang);
});
this.languages.forEach(item => item.selected(item.key === currentLang));
}
onBeforeShow() {

View file

@ -20,7 +20,7 @@ class MessageOpenPgpPopupView extends AbstractViewNext {
password: '',
submitRequest: false
});
this.privateKeys = ko.observableArray([]);
this.privateKeys = ko.observableArray();
this.resultCallback = null;

View file

@ -24,10 +24,10 @@ class PluginPopupView extends AbstractViewNext {
readme: ''
});
this.configures = ko.observableArray([]);
this.configures = ko.observableArray();
this.hasReadme = ko.computed(() => !!this.readme());
this.hasConfiguration = ko.computed(() => 0 < this.configures().length);
this.hasConfiguration = ko.computed(() => 0 < this.configures.length);
this.bDisabeCloseOnEsc = true;
this.sDefaultKeyScope = KeyState.All;
@ -40,7 +40,7 @@ class PluginPopupView extends AbstractViewNext {
const list = {};
list.Name = this.name();
this.configures().forEach(oItem => {
this.configures.forEach(oItem => {
let value = oItem.value();
if (false === value || true === value) {
value = value ? '1' : '0';

View file

@ -141,7 +141,7 @@ class MessageListMailBoxUserView extends AbstractViewNext {
read: () => 0 < MessageStore.messageListChecked().length,
write: (value) => {
value = !!value;
MessageStore.messageList().forEach(message => message.checked(value));
MessageStore.messageList.forEach(message => message.checked(value));
}
},
@ -152,10 +152,10 @@ class MessageListMailBoxUserView extends AbstractViewNext {
isIncompleteChecked: () => {
const c = MessageStore.messageListChecked().length;
return c && MessageStore.messageList().length > c;
return c && MessageStore.messageList.length > c;
},
hasMessages: () => 0 < this.messageList().length,
hasMessages: () => 0 < this.messageList.length,
hasCheckedOrSelectedLines: () => 0 < this.messageListCheckedOrSelected().length,
@ -219,7 +219,7 @@ class MessageListMailBoxUserView extends AbstractViewNext {
addEventListener('mailbox.message.show', e => {
const sFolder = e.detail.Folder, sUid = e.detail.Uid;
const message = this.messageList().find(
const message = this.messageList.find(
item => item && sFolder === item.folder && sUid === item.uid
);
@ -492,7 +492,7 @@ class MessageListMailBoxUserView extends AbstractViewNext {
case MessageSetAction.SetSeen:
folder = getFolderFromCacheList(sFolderFullNameRaw);
if (folder) {
MessageStore.messageList().forEach(message => {
MessageStore.messageList.forEach(message => {
if (message.isUnseen()) {
++cnt;
}
@ -518,7 +518,7 @@ class MessageListMailBoxUserView extends AbstractViewNext {
case MessageSetAction.UnsetSeen:
folder = getFolderFromCacheList(sFolderFullNameRaw);
if (folder) {
MessageStore.messageList().forEach(message => {
MessageStore.messageList.forEach(message => {
if (!message.isUnseen()) {
++cnt;
}
@ -675,7 +675,7 @@ class MessageListMailBoxUserView extends AbstractViewNext {
!this.messageListSearchDesc() &&
!this.messageListError() &&
!this.messageListEndThreadUid() &&
this.messageList().length &&
this.messageList.length &&
(this.isSpamFolder() || this.isTrashFolder())
);
}
@ -864,7 +864,7 @@ class MessageListMailBoxUserView extends AbstractViewNext {
prefetchNextTick() {
if (ifvisible && !this.bPrefetch && !ifvisible.now() && this.viewModelVisible) {
const message = this.messageList().find(
const message = this.messageList.find(
item => item && !hasRequestedMessage(item.folder, item.uid)
);
if (message) {

View file

@ -157,9 +157,9 @@ class MessageViewMailBoxUserView extends AbstractViewNext {
});
this.addComputables({
allowAttachmnetControls: () => this.attachmentsActions().length && Settings.capa(Capa.AttachmentsActions),
allowAttachmnetControls: () => this.attachmentsActions.length && Settings.capa(Capa.AttachmentsActions),
downloadAsZipAllowed: () => this.attachmentsActions().includes('zip') && this.allowAttachmnetControls(),
downloadAsZipAllowed: () => this.attachmentsActions.includes('zip') && this.allowAttachmnetControls(),
lastReplyAction: {
read: this.lastReplyAction_,
@ -206,7 +206,7 @@ class MessageViewMailBoxUserView extends AbstractViewNext {
this.addSubscribables({
showAttachmnetControls: v => this.message()
&& this.message().attachments().forEach(item => item && item.checked(!!v)),
&& this.message().attachments.forEach(item => item && item.checked(!!v)),
lastReplyAction_: value => Local.set(ClientSideKeyName.LastReplyAction, value),
@ -380,7 +380,7 @@ class MessageViewMailBoxUserView extends AbstractViewNext {
attachmentPreview(/*attachment*/) {
/*
if (attachment && attachment.isImage() && !attachment.isLinked && this.message() && this.message().attachments()) {
const items = this.message().attachments().map(item => {
const items = this.message().attachments.map(item => {
if (item && !item.isLinked && item.isImage()) {
if (item === attachment) {
index = listIndex;
@ -712,13 +712,10 @@ class MessageViewMailBoxUserView extends AbstractViewNext {
}
}
getAttachmentsHashes() {
const atts = this.message() ? this.message().attachments() : [];
return atts.map(item => (item && !item.isLinked && item.checked() ? item.download : '')).filter(v => v);
}
downloadAsZip() {
const hashes = this.getAttachmentsHashes();
const hashes = (this.message() ? this.message().attachments : [])
.map(item => (item && !item.isLinked && item.checked() ? item.download : ''))
.filter(v => v);
if (hashes.length) {
Remote.attachmentsActions('Zip', hashes, this.downloadAsZipLoading)
.then((result) => {