diff --git a/dev/Knoin/AbstractModel.js b/dev/Knoin/AbstractModel.js index 4ab6ad20a..d3f925a97 100644 --- a/dev/Knoin/AbstractModel.js +++ b/dev/Knoin/AbstractModel.js @@ -46,18 +46,20 @@ export class AbstractModel { /** Called by delegateRunOnDestroy */ onDestroy() { - /** clear ko.subscribe */ + /** dispose ko subscribables */ this.subscribables.forEach(dispose); /** clear object entries */ - Object.entries(this).forEach(([key, value]) => { +// Object.entries(this).forEach(([key, value]) => { + Object.values(this).forEach(value => { /** clear CollectionModel */ let arr = ko.isObservableArray(value) ? value() : value; arr && arr.onDestroy && value.onDestroy(); /** destroy ko.observable/ko.computed? */ dispose(value); /** clear object value */ - this[key] = null; +// this[key] = null; // TODO: issue with Contacts view }); +// this.subscribables = []; } /** diff --git a/dev/Model/ContactProperty.js b/dev/Model/ContactProperty.js index 7461b26bb..5950fa28b 100644 --- a/dev/Model/ContactProperty.js +++ b/dev/Model/ContactProperty.js @@ -4,6 +4,8 @@ import { i18n } from 'Common/Translator'; import { AbstractModel } from 'Knoin/AbstractModel'; +const trim = text => null == text ? "" : (text + "").trim(); + class ContactPropertyModel extends AbstractModel { /** * @param {number=} type = Enums.ContactPropertyType.Unknown @@ -34,6 +36,14 @@ class ContactPropertyModel extends AbstractModel { }); } + isType(type) { + return this.type && type === this.type(); + } + + isValid() { + return this.value && !!trim(this.value()); + } + toJSON() { return { type: this.type(), diff --git a/dev/View/Popup/Contacts.js b/dev/View/Popup/Contacts.js index d7cdbe42f..e0bc46974 100644 --- a/dev/View/Popup/Contacts.js +++ b/dev/View/Popup/Contacts.js @@ -29,8 +29,9 @@ import { ContactPropertyModel } from 'Model/ContactProperty'; import { popup, command, showScreenPopup, hideScreenPopup } from 'Knoin/Knoin'; import { AbstractViewNext } from 'Knoin/AbstractViewNext'; -const trim = text => null == text ? "" : (text + "").trim(), - CONTACTS_PER_PAGE = 50; +const CONTACTS_PER_PAGE = 50, + propertyIsMail = prop => prop.isType(ContactPropertyType.Email), + propertyIsName = prop => prop.isType(ContactPropertyType.FirstName) || prop.isType(ContactPropertyType.LastName); @popup({ name: 'View/Popup/Contacts', @@ -74,8 +75,6 @@ class ContactsPopupView extends AbstractViewNext { this.viewProperties = ko.observableArray([]); - const propertyFocused = property => !trim(property.value()) && !property.focused(); - /* // Somehow this is broken now when calling addNewProperty const fFastClearEmptyListHelper = list => { @@ -119,59 +118,44 @@ class ContactsPopupView extends AbstractViewNext { this.sDefaultKeyScope = KeyState.ContactList; + const +// propertyFocused = property => !property.isValid() && !property.focused(), + pagecount = () => Math.max(1, Math.ceil(this.contactsCount() / CONTACTS_PER_PAGE)); + this.addComputables({ - contactsPageCount: () => Math.max(1, Math.ceil(this.contactsCount() / CONTACTS_PER_PAGE)), + contactsPageCount: pagecount, - contactsPaginator: computedPaginatorHelper(this.contactsPage, this.contactsPageCount), + contactsPaginator: computedPaginatorHelper(this.contactsPage, pagecount), - viewPropertiesNames: () => - this.viewProperties().filter( - property => [ContactPropertyType.FirstName, ContactPropertyType.LastName].includes(property.type()) - ), + viewPropertiesNames: () => this.viewProperties().filter(propertyIsName), - viewPropertiesOther: () => - this.viewProperties().filter(property => [ContactPropertyType.Nick].includes(property.type())), + viewPropertiesEmails: () => this.viewProperties().filter(propertyIsMail), - viewPropertiesEmails: () => - this.viewProperties().filter(property => ContactPropertyType.Email === property.type()), + viewPropertiesOther: () => this.viewProperties().filter(property => property.isType(ContactPropertyType.Nick)), - viewPropertiesWeb: () => this.viewProperties().filter(property => ContactPropertyType.Web === property.type()), + viewPropertiesWeb: () => this.viewProperties().filter(property => property.isType(ContactPropertyType.Web)), - viewHasNonEmptyRequiredProperties: () => { - const names = this.viewPropertiesNames(), - emails = this.viewPropertiesEmails(), - fFilter = property => !!trim(property.value()); - - return !!(names.find(fFilter) || emails.find(fFilter)); - }, - - viewPropertiesPhones: () => - this.viewProperties().filter(property => ContactPropertyType.Phone === property.type()), - - viewPropertiesEmailsNonEmpty: () => this.viewPropertiesNames().filter(property => !!trim(property.value())), + viewPropertiesPhones: () => this.viewProperties().filter(property => property.isType(ContactPropertyType.Phone)), + contactHasValidName: () => !!this.viewProperties().find(prop => propertyIsName(prop) && prop.isValid()), +/* viewPropertiesEmailsEmptyAndOnFocused: () => this.viewPropertiesEmails().filter(propertyFocused), - viewPropertiesPhonesEmptyAndOnFocused: () => this.viewPropertiesPhones().filter(propertyFocused), - viewPropertiesWebEmptyAndOnFocused: () => this.viewPropertiesWeb().filter(propertyFocused), - viewPropertiesOtherEmptyAndOnFocused: () => this.viewPropertiesOther().filter(propertyFocused), - - contactsChecked: () => this.contacts().filter(item => item.checked()), - +*/ contactsCheckedOrSelected: () => { - const checked = this.contactsChecked(), + const checked = this.contacts().filter(item => item.checked && item.checked()), selected = this.currentContact(); return selected - ? checked.concat([selected]).unique() + ? [...checked, selected].unique() : checked; }, contactsCheckedOrSelectedUids: () => this.contactsCheckedOrSelected().map(contact => contact.id), - viewHash: () => '' + this.viewProperties().map(oItem => oItem.value()).join('') + viewHash: () => '' + this.viewProperties().map(property => property.value && property.value()).join('') }); this.search.subscribe(() => this.reloadContactList()); @@ -257,11 +241,10 @@ class ContactsPopupView extends AbstractViewNext { this.search(''); } - @command((self) => { - const bV = self.viewHasNonEmptyRequiredProperties(), - bReadOnly = self.viewReadOnly(); - return !self.viewSaving() && bV && !bReadOnly; - }) + @command(self => + !self.viewSaving() && !self.viewReadOnly() + && (self.contactHasValidName() || self.viewProperties().find(prop => propertyIsMail(prop) && prop.isValid())) + ) saveCommand() { this.viewSaving(true); this.viewSaveTrigger(SaveSettingsStep.Animate); @@ -339,7 +322,7 @@ class ContactsPopupView extends AbstractViewNext { } addNewOrFocusProperty(type, typeStr) { - const item = this.viewProperties().find(prop => type === prop.type()); + const item = this.viewProperties().find(prop => prop.isType(type)); if (item) { item.focused(true); } else { @@ -484,9 +467,8 @@ class ContactsPopupView extends AbstractViewNext { this.viewID(id); - delegateRunOnDestroy(this.viewProperties()); - - this.viewProperties([]); +// delegateRunOnDestroy(this.viewProperties()); +// this.viewProperties([]); this.viewProperties(contact.properties); this.watchDirty(false); diff --git a/snappymail/v/0.0.0/app/templates/Views/User/PopupsContacts.html b/snappymail/v/0.0.0/app/templates/Views/User/PopupsContacts.html index 4c0a7d143..f7b217c96 100644 --- a/snappymail/v/0.0.0/app/templates/Views/User/PopupsContacts.html +++ b/snappymail/v/0.0.0/app/templates/Views/User/PopupsContacts.html @@ -168,7 +168,7 @@