diff --git a/dev/Common/Selector.js b/dev/Common/Selector.js index 1876be3b0..56bd4012a 100644 --- a/dev/Common/Selector.js +++ b/dev/Common/Selector.js @@ -1,5 +1,6 @@ import ko from 'ko'; import { isArray } from 'Common/Utils'; +import { koComputable } from 'External/ko'; /* oCallbacks: @@ -28,8 +29,8 @@ export class Selector { sItemFocusedSelector ) { this.list = koList; - this.listChecked = ko.computed(() => this.list.filter(item => item.checked())).extend({ rateLimit: 0 }); - this.isListChecked = ko.computed(() => 0 < this.listChecked().length); + this.listChecked = koComputable(() => this.list.filter(item => item.checked())).extend({ rateLimit: 0 }); + this.isListChecked = koComputable(() => 0 < this.listChecked().length); this.focusedItem = koFocusedItem || ko.observable(null); this.selectedItem = koSelectedItem || ko.observable(null); diff --git a/dev/Component/AbstractInput.js b/dev/Component/AbstractInput.js index 0648a3390..9fec3ea44 100644 --- a/dev/Component/AbstractInput.js +++ b/dev/Component/AbstractInput.js @@ -2,6 +2,7 @@ import ko from 'ko'; import { pInt } from 'Common/Utils'; import { SaveSettingsStep } from 'Common/Enums'; import { AbstractComponent } from 'Component/Abstract'; +import { koComputable } from 'External/ko'; class AbstractInput extends AbstractComponent { /** @@ -18,7 +19,7 @@ class AbstractInput extends AbstractComponent { this.labeled = null != params.label; - let size = params.size || 0; + let size = 0 < params.size ? 'span' + params.size : ''; if (this.trigger) { const classForTrigger = ko.observable(''), @@ -38,13 +39,13 @@ class AbstractInput extends AbstractComponent { setTriggerState(this.trigger()); - this.className = ko.computed(() => - ((0 < size ? 'span' + size : '') + ' settings-saved-trigger-input ' + classForTrigger()).trim() + this.className = koComputable(() => + (size + ' settings-saved-trigger-input ' + classForTrigger()).trim() ); this.disposable.push(this.trigger.subscribe(setTriggerState, this)); } else { - this.className = ko.computed(() => 0 < size ? 'span' + size : ''); + this.className = size; } this.disposable.push(this.className); diff --git a/dev/External/ko.js b/dev/External/ko.js index f3cec92bd..22b7e501e 100644 --- a/dev/External/ko.js +++ b/dev/External/ko.js @@ -3,6 +3,13 @@ import { doc, createElement } from 'Common/Globals'; import { SaveSettingsStep } from 'Common/Enums'; import { arrayLength, isFunction } from 'Common/Utils'; +/** + * The value of the pureComputed observable shouldn’t vary based on the + * number of evaluations or other “hidden” information. Its value should be + * based solely on the values of other observables in the application + */ +export const koComputable = ko.pureComputed; + ko.bindingHandlers.tooltipErrorTip = { init: (element, fValueAccessor) => { doc.addEventListener('click', () => { diff --git a/dev/Knoin/Knoin.js b/dev/Knoin/Knoin.js index 134776b42..e4805a708 100644 --- a/dev/Knoin/Knoin.js +++ b/dev/Knoin/Knoin.js @@ -1,5 +1,5 @@ import ko from 'ko'; - +import { koComputable } from 'External/ko'; import { doc, $htmlCL, elementById } from 'Common/Globals'; import { isFunction, forEachObjectValue, forEachObjectEntry } from 'Common/Utils'; @@ -271,9 +271,9 @@ export const fResult.isCommand = true; if (isFunction(fCanExecute)) { - fResult.canExecute = ko.computed(() => fResult && fResult.enabled() && fCanExecute.call(null)); + fResult.canExecute = koComputable(() => fResult && fResult.enabled() && fCanExecute.call(null)); } else { - fResult.canExecute = ko.computed(() => fResult && fResult.enabled() && !!fCanExecute); + fResult.canExecute = koComputable(() => fResult && fResult.enabled() && !!fCanExecute); } return fResult; @@ -355,8 +355,8 @@ export const fn.enabled = ko.observable(true); fn.canExecute = (typeof canExecute === 'function') - ? ko.computed(() => fn.enabled() && canExecute.call(thisArg, thisArg)) - : ko.computed(() => fn.enabled()); + ? koComputable(() => fn.enabled() && canExecute.call(thisArg, thisArg)) + : koComputable(() => fn.enabled()); thisArg[key] = fn; }); diff --git a/dev/Model/FilterCondition.js b/dev/Model/FilterCondition.js index c4a06387a..5bc7cd858 100644 --- a/dev/Model/FilterCondition.js +++ b/dev/Model/FilterCondition.js @@ -1,4 +1,4 @@ -import ko from 'ko'; +import { koComputable } from 'External/ko'; import { AbstractModel } from 'Knoin/AbstractModel'; @@ -43,7 +43,7 @@ export class FilterConditionModel extends AbstractModel { valueSecondError: false }); - this.template = ko.computed(() => { + this.template = koComputable(() => { const template = 'SettingsFiltersCondition'; switch (this.field()) { case FilterConditionField.Body: diff --git a/dev/Model/FolderCollection.js b/dev/Model/FolderCollection.js index 8513e3ce2..f8a6d2115 100644 --- a/dev/Model/FolderCollection.js +++ b/dev/Model/FolderCollection.js @@ -20,6 +20,8 @@ import { i18n, trigger as translatorTrigger } from 'Common/Translator'; import { AbstractModel } from 'Knoin/AbstractModel'; +import { koComputable } from 'External/ko'; + //import { mailBox } from 'Common/Links'; const @@ -265,7 +267,7 @@ export class FolderModel extends AbstractModel { type && 'mail' != type && folder.kolabType(type); - folder.messageCountAll = ko.computed({ + folder.messageCountAll = koComputable({ read: folder.privateMessageCountAll, write: (iValue) => { if (isPosNumeric(iValue)) { @@ -277,7 +279,7 @@ export class FolderModel extends AbstractModel { }) .extend({ notify: 'always' }); - folder.messageCountUnread = ko.computed({ + folder.messageCountUnread = koComputable({ read: folder.privateMessageCountUnread, write: (value) => { if (isPosNumeric(value)) { diff --git a/dev/Model/Identity.js b/dev/Model/Identity.js index 3fa72b9f4..63daa343b 100644 --- a/dev/Model/Identity.js +++ b/dev/Model/Identity.js @@ -1,4 +1,4 @@ -import ko from 'ko'; +import { koComputable } from 'External/ko'; import { AbstractModel } from 'Knoin/AbstractModel'; @@ -24,7 +24,7 @@ export class IdentityModel extends AbstractModel { deleteAccess: false }); - this.canBeDeleted = ko.computed(() => !!this.id()); + this.canBeDeleted = koComputable(() => !!this.id()); } /** diff --git a/dev/Settings/User/Folders.js b/dev/Settings/User/Folders.js index b3a3e5b61..7a6030d8f 100644 --- a/dev/Settings/User/Folders.js +++ b/dev/Settings/User/Folders.js @@ -1,4 +1,5 @@ import ko from 'ko'; +import { koComputable } from 'External/ko'; import { Notification } from 'Common/Enums'; import { FolderMetadataKeys } from 'Common/EnumsUser'; @@ -25,7 +26,7 @@ const folderForDeletion = ko.observable(null).deleteAccessHelper(); export class FoldersUserSettings /*extends AbstractViewSettings*/ { constructor() { - this.showKolab = ko.computed(() => FolderUserStore.hasCapability('METADATA') && Settings.capa(Capa.Kolab)); + this.showKolab = koComputable(() => FolderUserStore.hasCapability('METADATA') && Settings.capa(Capa.Kolab)); this.defaultOptionsAfterRender = defaultOptionsAfterRender; this.kolabTypeOptions = ko.observableArray(); let i18nFilter = key => i18n('SETTINGS_FOLDERS/TYPE_' + key); @@ -48,7 +49,7 @@ export class FoldersUserSettings /*extends AbstractViewSettings*/ { this.folderListError = FolderUserStore.folderListError; this.hideUnsubscribed = SettingsUserStore.hideUnsubscribed; - this.loading = ko.computed(() => { + this.loading = koComputable(() => { const loading = FolderUserStore.foldersLoading(), creating = FolderUserStore.foldersCreating(), deleting = FolderUserStore.foldersDeleting(), diff --git a/dev/Settings/User/Security.js b/dev/Settings/User/Security.js index 85cf60d22..8c765b71b 100644 --- a/dev/Settings/User/Security.js +++ b/dev/Settings/User/Security.js @@ -1,4 +1,5 @@ import ko from 'ko'; +import { koComputable } from 'External/ko'; import { pInt, settingsSaveHelperSimpleFunction } from 'Common/Utils'; import { Capa, SaveSettingsStep } from 'Common/Enums'; @@ -17,7 +18,7 @@ export class SecurityUserSettings /*extends AbstractViewSettings*/ { this.autoLogoutTrigger = ko.observable(SaveSettingsStep.Idle); let i18nLogout = (key, params) => i18n('SETTINGS_SECURITY/AUTOLOGIN_' + key, params); - this.autoLogoutOptions = ko.computed(() => { + this.autoLogoutOptions = koComputable(() => { translatorTrigger(); return [ { id: 0, name: i18nLogout('NEVER_OPTION_NAME') }, diff --git a/dev/Stores/User/Folder.js b/dev/Stores/User/Folder.js index 0b1a819e3..3d69905bb 100644 --- a/dev/Stores/User/Folder.js +++ b/dev/Stores/User/Folder.js @@ -1,4 +1,5 @@ import ko from 'ko'; +import { koComputable } from 'External/ko'; import { FolderType, FolderSortMode } from 'Common/EnumsUser'; import { UNUSED_OPTION_VALUE } from 'Common/Consts'; @@ -100,7 +101,7 @@ export const FolderUserStore = new class { archiveFolder: fSetSystemFolderType(FolderType.Archive) }); - self.quotaPercentage = ko.computed(() => { + self.quotaPercentage = koComputable(() => { const quota = self.quotaLimit(), usage = self.quotaUsage(); return 0 < quota ? Math.ceil((usage / quota) * 100) : 0; }); diff --git a/dev/Stores/User/Settings.js b/dev/Stores/User/Settings.js index 41ee906fa..f944474b5 100644 --- a/dev/Stores/User/Settings.js +++ b/dev/Stores/User/Settings.js @@ -1,4 +1,5 @@ import ko from 'ko'; +import { koComputable } from 'External/ko'; import { Layout, EditorDefaultType } from 'Common/EnumsUser'; import { pInt, addObservablesTo } from 'Common/Utils'; @@ -39,7 +40,7 @@ export const SettingsUserStore = new class { self.init(); - self.usePreviewPane = ko.computed(() => Layout.NoPreview !== self.layout() && !ThemeStore.isMobile()); + self.usePreviewPane = koComputable(() => Layout.NoPreview !== self.layout() && !ThemeStore.isMobile()); const toggleLayout = () => { const value = ThemeStore.isMobile() ? Layout.NoPreview : self.layout(); diff --git a/dev/View/Popup/AdvancedSearch.js b/dev/View/Popup/AdvancedSearch.js index 4f2eae169..16f2d1570 100644 --- a/dev/View/Popup/AdvancedSearch.js +++ b/dev/View/Popup/AdvancedSearch.js @@ -1,4 +1,4 @@ -import ko from 'ko'; +import { koComputable } from 'External/ko'; import { i18n, trigger as translatorTrigger } from 'Common/Translator'; @@ -25,10 +25,10 @@ class AdvancedSearchPopupView extends AbstractViewPopup { unseen: false }); - this.showMultisearch = ko.computed(() => FolderUserStore.hasCapability('MULTISEARCH')); + this.showMultisearch = koComputable(() => FolderUserStore.hasCapability('MULTISEARCH')); let prefix = 'SEARCH/LABEL_ADV_DATE_'; - this.selectedDates = ko.computed(() => { + this.selectedDates = koComputable(() => { translatorTrigger(); return [ { id: -1, name: i18n(prefix + 'ALL') }, @@ -42,7 +42,7 @@ class AdvancedSearchPopupView extends AbstractViewPopup { }); prefix = 'SEARCH/LABEL_ADV_SUBFOLDERS_'; - this.selectedTree = ko.computed(() => { + this.selectedTree = koComputable(() => { translatorTrigger(); return [ { id: '', name: i18n(prefix + 'NONE') }, diff --git a/dev/View/Popup/Filter.js b/dev/View/Popup/Filter.js index f04faa1f3..ecbf0a738 100644 --- a/dev/View/Popup/Filter.js +++ b/dev/View/Popup/Filter.js @@ -1,4 +1,5 @@ import ko from 'ko'; +import { koComputable } from 'External/ko'; import { FilterAction } from 'Model/Filter'; import { FilterConditionField, FilterConditionType } from 'Model/FilterCondition'; @@ -27,7 +28,7 @@ class FilterPopupView extends AbstractViewPopup { this.fTrueCallback = null; this.defaultOptionsAfterRender = defaultOptionsAfterRender; - this.folderSelectList = ko.computed(() => + this.folderSelectList = koComputable(() => folderListOptionsBuilder( [SettingsGet('SieveAllowFileintoInbox') ? '' : 'INBOX'], [['', '']], diff --git a/dev/View/Popup/FolderCreate.js b/dev/View/Popup/FolderCreate.js index 26db48395..efd26ef9e 100644 --- a/dev/View/Popup/FolderCreate.js +++ b/dev/View/Popup/FolderCreate.js @@ -1,4 +1,4 @@ -import ko from 'ko'; +import { koComputable } from 'External/ko'; import { Notification } from 'Common/Enums'; import { UNUSED_OPTION_VALUE } from 'Common/Consts'; @@ -26,7 +26,7 @@ class FolderCreatePopupView extends AbstractViewPopup { selectedParentValue: UNUSED_OPTION_VALUE }); - this.parentFolderSelectList = ko.computed(() => + this.parentFolderSelectList = koComputable(() => folderListOptionsBuilder( [], [['', '']], diff --git a/dev/View/Popup/FolderSystem.js b/dev/View/Popup/FolderSystem.js index ccd855018..92004cc36 100644 --- a/dev/View/Popup/FolderSystem.js +++ b/dev/View/Popup/FolderSystem.js @@ -1,4 +1,5 @@ import ko from 'ko'; +import { koComputable } from 'External/ko'; import { SetSystemFoldersNotification } from 'Common/EnumsUser'; import { UNUSED_OPTION_VALUE } from 'Common/Consts'; @@ -24,7 +25,7 @@ class FolderSystemPopupView extends AbstractViewPopup { this.notification = ko.observable(''); - this.folderSelectList = ko.computed(() => + this.folderSelectList = koComputable(() => folderListOptionsBuilder( FolderUserStore.folderListSystemNames(), [ diff --git a/dev/View/Popup/Languages.js b/dev/View/Popup/Languages.js index 051c3e775..3a5fd9990 100644 --- a/dev/View/Popup/Languages.js +++ b/dev/View/Popup/Languages.js @@ -1,4 +1,5 @@ import ko from 'ko'; +import { koComputable } from 'External/ko'; import { convertLangName } from 'Common/Translator'; @@ -13,7 +14,7 @@ class LanguagesPopupView extends AbstractViewPopup { this.langs = ko.observableArray(); - this.languages = ko.computed(() => { + this.languages = koComputable(() => { const userLanguage = this.userLanguage(); return this.langs.map(language => ({ key: language, diff --git a/dev/View/User/MailBox/MessageList.js b/dev/View/User/MailBox/MessageList.js index bbec32fbe..08c7a2623 100644 --- a/dev/View/User/MailBox/MessageList.js +++ b/dev/View/User/MailBox/MessageList.js @@ -64,10 +64,6 @@ export class MailMessageList extends AbstractViewRight { this.messageList = MessageUserStore.list; - this.sortSupported = ko.computed(() => - FolderUserStore.hasCapability('SORT') | FolderUserStore.hasCapability('ESORT') - ); - this.composeInEdit = AppUserStore.composeInEdit; this.isMobile = ThemeStore.isMobile; @@ -107,6 +103,9 @@ export class MailMessageList extends AbstractViewRight { this.addComputables({ + sortSupported: () => + FolderUserStore.hasCapability('SORT') | FolderUserStore.hasCapability('ESORT'), + folderMenuForMove: () => folderListOptionsBuilder( [FolderUserStore.currentFolderFullName()], diff --git a/dev/View/User/SystemDropDown.js b/dev/View/User/SystemDropDown.js index b2f21032b..d4be86332 100644 --- a/dev/View/User/SystemDropDown.js +++ b/dev/View/User/SystemDropDown.js @@ -20,6 +20,7 @@ import { ThemeStore } from 'Stores/Theme'; import Remote from 'Remote/User/Fetch'; import { getNotification } from 'Common/Translator'; //import { clearCache } from 'Common/Cache'; +//import { koComputable } from 'External/ko'; export class SystemDropDownUserView extends AbstractViewRight { constructor() { @@ -32,8 +33,8 @@ export class SystemDropDownUserView extends AbstractViewRight { this.accounts = AccountUserStore.accounts; this.accountsLoading = AccountUserStore.loading; /* - this.accountsUnreadCount = : ko.computed(() => 0); - this.accountsUnreadCount = : ko.computed(() => AccountUserStore.accounts().reduce((result, item) => result + item.count(), 0)); + this.accountsUnreadCount = : koComputable(() => 0); + this.accountsUnreadCount = : koComputable(() => AccountUserStore.accounts().reduce((result, item) => result + item.count(), 0)); */ this.addObservables({