mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-07-11 00:14:50 +03:00
Cleanup calls to Knockout observableArray
Improved Knockout observableArray
This commit is contained in:
parent
fa5476e486
commit
b6f0b634fb
47 changed files with 251 additions and 276 deletions
|
|
@ -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
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 => {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ class MessageOpenPgpPopupView extends AbstractViewNext {
|
|||
password: '',
|
||||
submitRequest: false
|
||||
});
|
||||
this.privateKeys = ko.observableArray([]);
|
||||
this.privateKeys = ko.observableArray();
|
||||
|
||||
this.resultCallback = null;
|
||||
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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) => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue