import ko from 'ko'; import { FolderType, FolderSortMode } from 'Common/EnumsUser'; import { UNUSED_OPTION_VALUE } from 'Common/Consts'; import { addObservablesTo, addSubscribablesTo } from 'Common/Utils'; import { getFolderInboxName, getFolderFromCacheList } from 'Common/Cache'; import { SettingsGet } from 'Common/Globals'; export const FolderUserStore = new class { constructor() { addObservablesTo(this, { /** * To use "checkable" option in /#/settings/folders * When true, getNextFolderNames only lists system and "checkable" folders * and affects the update of unseen count * Auto set to true when amount of folders > folderSpecLimit to prevent requests overload, * see application.ini [labs] folders_spec_limit */ displaySpecSetting: false, /** * If the IMAP server supports SORT */ sortSupported: false, // sortMode: '', sentFolder: '', draftFolder: '', spamFolder: '', trashFolder: '', archiveFolder: '', folderListOptimized: false, folderListError: '', foldersLoading: false, foldersCreating: false, foldersDeleting: false, foldersRenaming: false, foldersInboxUnreadCount: 0 }); this.sortMode = ko.observable('').extend({ limitedList: Object.values(FolderSortMode) }); this.namespace = ''; this.folderList = ko.observableArray(); this.currentFolder = ko.observable(null).extend({ toggleSubscribeProperty: [this, 'selected'] }); this.sieveAllowFileintoInbox = !!SettingsGet('SieveAllowFileintoInbox'); this.draftFolderNotEnabled = ko.computed( () => !this.draftFolder() || UNUSED_OPTION_VALUE === this.draftFolder() ); this.foldersListWithSingleInboxRootFolder = ko.computed( () => !this.folderList.find(folder => folder && !folder.isSystemFolder() && folder.visible()) ); this.currentFolderFullNameRaw = ko.computed(() => (this.currentFolder() ? this.currentFolder().fullNameRaw : '')); this.currentFolderFullName = ko.computed(() => (this.currentFolder() ? this.currentFolder().fullName : '')); this.currentFolderFullNameHash = ko.computed(() => (this.currentFolder() ? this.currentFolder().fullNameHash : '')); this.foldersChanging = ko.computed(() => { const loading = this.foldersLoading(), creating = this.foldersCreating(), deleting = this.foldersDeleting(), renaming = this.foldersRenaming(); return loading || creating || deleting || renaming; }); this.folderListSystemNames = ko.computed(() => { const list = [getFolderInboxName()], others = [this.sentFolder(), this.draftFolder(), this.spamFolder(), this.trashFolder(), this.archiveFolder()]; this.folderList().length && others.forEach(name => name && UNUSED_OPTION_VALUE !== name && list.push(name)); return list; }); this.folderListSystem = ko.computed(() => this.folderListSystemNames().map(name => getFolderFromCacheList(name)).filter(v => v) ); const fRemoveSystemFolderType = (observable) => () => { const folder = getFolderFromCacheList(observable()); folder && folder.type(FolderType.User); }, fSetSystemFolderType = type => value => { const folder = getFolderFromCacheList(value); folder && folder.type(type); }; this.sentFolder.subscribe(fRemoveSystemFolderType(this.sentFolder), this, 'beforeChange'); this.draftFolder.subscribe(fRemoveSystemFolderType(this.draftFolder), this, 'beforeChange'); this.spamFolder.subscribe(fRemoveSystemFolderType(this.spamFolder), this, 'beforeChange'); this.trashFolder.subscribe(fRemoveSystemFolderType(this.trashFolder), this, 'beforeChange'); this.archiveFolder.subscribe(fRemoveSystemFolderType(this.archiveFolder), this, 'beforeChange'); addSubscribablesTo(this, { sentFolder: fSetSystemFolderType(FolderType.Sent), draftFolder: fSetSystemFolderType(FolderType.Drafts), spamFolder: fSetSystemFolderType(FolderType.Spam), trashFolder: fSetSystemFolderType(FolderType.Trash), archiveFolder: fSetSystemFolderType(FolderType.Archive) }); } /** * @returns {Array} */ getNextFolderNames(ttl) { const result = [], limit = 10, utc = Date.now(), timeout = utc - ttl, timeouts = [], bDisplaySpecSetting = this.displaySpecSetting(), fSearchFunction = (list) => { list.forEach(folder => { if ( folder && folder.selectable && folder.exists && timeout > folder.expires && (folder.isSystemFolder() || (folder.subscribed() && (folder.checkable() || !bDisplaySpecSetting))) ) { timeouts.push([folder.expires, folder.fullNameRaw]); } if (folder && folder.subFolders.length) { fSearchFunction(folder.subFolders()); } }); }; fSearchFunction(this.folderList()); timeouts.sort((a, b) => (a[0] < b[0]) ? -1 : (a[0] > b[0] ? 1 : 0)); timeouts.find(aItem => { const folder = getFolderFromCacheList(aItem[1]); if (folder) { folder.expires = utc; result.push(aItem[1]); } return limit <= result.length; }); return result.filter((value, index, self) => self.indexOf(value) == index); } };