From 732b6eb64175e225a5c9448de510e9c759959648 Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Fri, 2 Sep 2022 11:52:07 +0200 Subject: [PATCH] Use JavaScript Optional chaining --- dev/Common/Audio.js | 4 +-- dev/Common/Cache.js | 9 +++---- dev/Common/File.js | 2 +- dev/Common/Folders.js | 4 +-- dev/Common/Globals.js | 2 +- dev/Common/Html.js | 19 +++++++------- dev/Common/Plugins.js | 7 ++--- dev/Common/Selector.js | 2 +- dev/Common/Translator.js | 2 +- dev/Common/Utils.js | 3 +-- dev/Common/UtilsUser.js | 8 +++--- dev/Component/AbstractInput.js | 2 +- dev/Component/EmailAddresses.js | 6 ++--- dev/External/User/ko.js | 16 ++++++------ dev/External/ko.js | 8 +++--- dev/Knoin/AbstractModel.js | 5 ++-- dev/Knoin/AbstractViews.js | 2 +- dev/Knoin/Knoin.js | 39 +++++++++++++--------------- dev/Model/AbstractCollection.js | 2 +- dev/Model/Email.js | 4 +-- dev/Model/EmailCollection.js | 2 +- dev/Model/FolderCollection.js | 6 ++--- dev/Model/Message.js | 4 +-- dev/Remote/AbstractFetch.js | 12 ++++----- dev/Remote/User/Fetch.js | 4 +-- dev/Screen/AbstractSettings.js | 8 +++--- dev/Screen/User/MailBox.js | 2 +- dev/Settings/User/Accounts.js | 6 ++--- dev/Settings/User/Filters.js | 2 +- dev/Settings/User/Themes.js | 8 ++---- dev/Sieve/View/Filter.js | 3 +-- dev/Stores/Admin/Package.js | 2 +- dev/Stores/User/App.js | 2 +- dev/Stores/User/Contact.js | 4 +-- dev/Stores/User/Folder.js | 15 +++-------- dev/Stores/User/GnuPG.js | 16 ++++++------ dev/Stores/User/Message.js | 2 +- dev/Stores/User/Messagelist.js | 7 +++-- dev/Stores/User/Notification.js | 8 +++--- dev/Stores/User/OpenPGP.js | 2 +- dev/Stores/User/Pgp.js | 2 +- dev/View/Popup/Account.js | 4 +-- dev/View/Popup/Compose.js | 32 +++++++++++------------ dev/View/Popup/Contacts.js | 8 +++--- dev/View/Popup/Domain.js | 2 +- dev/View/Popup/Identity.js | 4 +-- dev/View/Popup/Languages.js | 2 +- dev/View/Popup/OpenPgpGenerate.js | 2 +- dev/View/User/Login.js | 4 +-- dev/View/User/MailBox/FolderList.js | 6 ++--- dev/View/User/MailBox/MessageList.js | 10 +++---- dev/View/User/MailBox/MessageView.js | 20 +++++++------- dev/View/User/SystemDropDown.js | 2 +- dev/dragdropgecko.js | 4 +-- dev/shortcuts.js | 5 ++-- 55 files changed, 169 insertions(+), 199 deletions(-) diff --git a/dev/Common/Audio.js b/dev/Common/Audio.js index 4d7d5a862..2a34fc6d0 100644 --- a/dev/Common/Audio.js +++ b/dev/Common/Audio.js @@ -4,7 +4,7 @@ import { addObservablesTo } from 'External/ko'; let notificator = null, player = null, - canPlay = type => player && !!player.canPlayType(type).replace('no', ''), + canPlay = type => !!player?.canPlayType(type).replace('no', ''), audioCtx = window.AudioContext || window.webkitAudioContext, @@ -92,7 +92,7 @@ export const SMAudio = new class { } pause() { - player && player.pause(); + player?.pause(); fireEvent('audio.stop'); } diff --git a/dev/Common/Cache.js b/dev/Common/Cache.js index 3e7ff57b6..c0d9cc9c8 100644 --- a/dev/Common/Cache.js +++ b/dev/Common/Cache.js @@ -37,8 +37,7 @@ export const * @param {string} folderHash * @returns {string} */ - getFolderFullName = folderHash => - folderHash && FOLDERS_NAME_CACHE[folderHash] ? FOLDERS_NAME_CACHE[folderHash] : '', + getFolderFullName = folderHash => (folderHash && FOLDERS_NAME_CACHE[folderHash]) || '', /** * @param {string} folderHash @@ -79,9 +78,7 @@ export class MessageFlagsCache * @returns {bool} */ static hasFlag(folderFullName, uid, flag) { - return MESSAGE_FLAGS_CACHE[folderFullName] - && MESSAGE_FLAGS_CACHE[folderFullName][uid] - && MESSAGE_FLAGS_CACHE[folderFullName][uid].includes(flag); + return MESSAGE_FLAGS_CACHE[folderFullName]?.[uid]?.includes(flag); } /** @@ -90,7 +87,7 @@ export class MessageFlagsCache * @returns {?Array} */ static getFor(folderFullName, uid) { - return MESSAGE_FLAGS_CACHE[folderFullName] && MESSAGE_FLAGS_CACHE[folderFullName][uid]; + return MESSAGE_FLAGS_CACHE[folderFullName]?.[uid]; } /** diff --git a/dev/Common/File.js b/dev/Common/File.js index aab390c4d..9cf850106 100644 --- a/dev/Common/File.js +++ b/dev/Common/File.js @@ -256,7 +256,7 @@ export const FileInfo = { .map(item => item ? FileInfo.getIconClass(FileInfo.getExtension(item.fileName), item.mimeType) : '') .validUnique(); - return (icons && 1 === icons.length && 'icon-file' !== icons[0]) + return (1 === icons?.length && 'icon-file' !== icons[0]) ? icons[0] : 'icon-attachment'; } diff --git a/dev/Common/Folders.js b/dev/Common/Folders.js index b75bf7cfc..86f77451b 100644 --- a/dev/Common/Folders.js +++ b/dev/Common/Folders.js @@ -56,7 +56,7 @@ fetchFolderInformation = (fCallback, folder, list = []) => { Remote.request('FolderInformation', fCallback, { Folder: folder, FlagsUids: uids, - UidNext: (folderFromCache && folderFromCache.uidNext) || 0 // Used to check for new messages + UidNext: folderFromCache?.uidNext || 0 // Used to check for new messages }); } else if (SettingsUserStore.useThreads()) { MessagelistUserStore.reloadFlagsAndCachedMessage(); @@ -134,7 +134,7 @@ refreshFoldersInterval = 300000, * @param {Array=} list = [] */ folderInformation = (folder, list) => { - if (folder && folder.trim()) { + if (folder?.trim()) { fetchFolderInformation( (iError, data) => { if (!iError && data.Result) { diff --git a/dev/Common/Globals.js b/dev/Common/Globals.js index 48f860880..22f4b4e94 100644 --- a/dev/Common/Globals.js +++ b/dev/Common/Globals.js @@ -31,7 +31,7 @@ export const new CustomEvent(name, {detail:detail, cancelable: !!cancelable}) ), - formFieldFocused = () => doc.activeElement && doc.activeElement.matches('input,textarea'), + formFieldFocused = () => doc.activeElement?.matches('input,textarea'), addShortcut = (...args) => shortcuts.add(...args), diff --git a/dev/Common/Html.js b/dev/Common/Html.js index 1d8254ca4..30df92788 100644 --- a/dev/Common/Html.js +++ b/dev/Common/Html.js @@ -28,7 +28,7 @@ export const * @param {string} text * @returns {string} */ - encodeHtml = text => (text && text.toString ? text.toString() : '' + text).replace(htmlre, m => htmlmap[m]), + encodeHtml = text => (text?.toString?.() || '' + text).replace(htmlre, m => htmlmap[m]), /** * Clears the Message Html for viewing @@ -47,7 +47,7 @@ export const findAttachmentByCid = cid => oAttachments.findByCid(cid), findLocationByCid = cid => { const attachment = findAttachmentByCid(cid); - return attachment && attachment.contentLocation ? attachment : 0; + return attachment?.contentLocation ? attachment : 0; }, // convert body attributes to CSS @@ -256,7 +256,7 @@ export const value = value.slice(4); setAttribute('data-x-src-cid', value); attachment = findAttachmentByCid(value); - if (attachment && attachment.download) { + if (attachment?.download) { oElement.src = attachment.linkPreview(); attachment.isInline(true); attachment.isLinked(true); @@ -320,7 +320,7 @@ export const let lowerUrl = found.toLowerCase(); if ('cid:' === lowerUrl.slice(0, 4)) { const attachment = findAttachmentByCid(found); - if (attachment && attachment.linkPreview && name) { + if (attachment?.linkPreview && name) { oStyle[property] = "url('" + attachment.linkPreview() + "')"; attachment.isInline(true); attachment.isLinked(true); @@ -434,9 +434,8 @@ export const parent = node, ordered = 'OL' == node.tagName, i = 0; - while (parent && parent.parentNode && parent.parentNode.closest) { - parent = parent.parentNode.closest('ol,ul'); - parent && (prefix = ' ' + prefix); + while ((parent = parent?.parentNode?.closest('ol,ul'))) { + prefix = ' ' + prefix; } node.querySelectorAll(':scope > li').forEach(li => { li.prepend('\n' + prefix + (ordered ? `${++i}. ` : ' * ')); @@ -567,7 +566,7 @@ export class HtmlEditor { editor.on('focus', () => this.blurTimer && clearTimeout(this.blurTimer)); editor.on('mode', () => { this.blurTrigger(); - this.onModeChange && this.onModeChange(!this.isPlain()); + this.onModeChange?.(!this.isPlain()); }); } } @@ -575,7 +574,7 @@ export class HtmlEditor { blurTrigger() { if (this.onBlur) { clearTimeout(this.blurTimer); - this.blurTimer = setTimeout(() => this.onBlur && this.onBlur(), 200); + this.blurTimer = setTimeout(() => this.onBlur?.(), 200); } } @@ -685,7 +684,7 @@ export class HtmlEditor { hasFocus() { try { - return this.editor && !!this.editor.focusManager.hasFocus; + return !!this.editor?.focusManager.hasFocus; } catch (e) { return false; } diff --git a/dev/Common/Plugins.js b/dev/Common/Plugins.js index 694930c1f..ed0469ba8 100644 --- a/dev/Common/Plugins.js +++ b/dev/Common/Plugins.js @@ -49,10 +49,7 @@ export function runSettingsViewModelHooks(admin) { * @param {string} name * @returns {?} */ -rl.pluginSettingsGet = (pluginSection, name) => { - let plugins = SettingsGet('Plugins'); - plugins = plugins && null != plugins[pluginSection] ? plugins[pluginSection] : null; - return plugins ? (null == plugins[name] ? null : plugins[name]) : null; -}; +rl.pluginSettingsGet = (pluginSection, name) => + SettingsGet('Plugins')?.[pluginSection]?.[name]; rl.pluginPopupView = AbstractViewPopup; diff --git a/dev/Common/Selector.js b/dev/Common/Selector.js index f413fd76c..8d0921384 100644 --- a/dev/Common/Selector.js +++ b/dev/Common/Selector.js @@ -422,7 +422,7 @@ export class Selector { lineUid = ''; const uid = this.getItemUid(item); - if (event && event.shiftKey) { + if (event?.shiftKey) { if (uid && this.sLastUid && uid !== this.sLastUid) { list = this.list(); checked = item.checked(); diff --git a/dev/Common/Translator.js b/dev/Common/Translator.js index 852bd36d1..933f22302 100644 --- a/dev/Common/Translator.js +++ b/dev/Common/Translator.js @@ -142,7 +142,7 @@ export const * @param {Function=} langCallback = null */ initOnStartOrLangChange = (startCallback, langCallback = null) => { - startCallback && startCallback(); + startCallback?.(); startCallback && trigger.subscribe(startCallback); langCallback && trigger.subscribe(langCallback); }, diff --git a/dev/Common/Utils.js b/dev/Common/Utils.js index 98cc9cffd..862f4c9fc 100644 --- a/dev/Common/Utils.js +++ b/dev/Common/Utils.js @@ -26,8 +26,7 @@ export const .trim(), defaultOptionsAfterRender = (domItem, item) => - domItem && item && undefined !== item.disabled - && domItem.classList.toggle('disabled', domItem.disabled = item.disabled), + item && undefined !== item.disabled && domItem?.classList.toggle('disabled', domItem.disabled = item.disabled), // unescape(encodeURIComponent()) makes the UTF-16 DOMString to an UTF-8 string b64EncodeJSON = data => btoa(unescape(encodeURIComponent(JSON.stringify(data)))), diff --git a/dev/Common/UtilsUser.js b/dev/Common/UtilsUser.js index a45fee974..09a894194 100644 --- a/dev/Common/UtilsUser.js +++ b/dev/Common/UtilsUser.js @@ -131,7 +131,7 @@ computedPaginatorHelper = (koCurrentPage, koPageCount) => { * @returns {boolean} */ mailToHelper = mailToUrl => { - if (mailToUrl && 'mailto:' === mailToUrl.slice(0, 7).toLowerCase()) { + if ('mailto:' === mailToUrl?.slice(0, 7).toLowerCase()) { mailToUrl = mailToUrl.slice(7).split('?'); const @@ -181,7 +181,7 @@ setLayoutResizer = (source, target, sClientSideKeyName, mode) => target.removeAttribute('style'); source.removeAttribute('style'); } - source.observer && source.observer.disconnect(); + source.observer?.disconnect(); // source.classList.toggle('resizable', mode); if (mode) { const length = Local.get(sClientSideKeyName + mode) || SettingsGet('Resizer' + sClientSideKeyName + mode), @@ -248,7 +248,7 @@ setLayoutResizer = (source, target, sClientSideKeyName, mode) => } source.layoutResizer.mode = mode; source.layoutResizer.key = sClientSideKeyName; - source.observer && source.observer.observe(source, { box: 'border-box' }); + source.observer?.observe(source, { box: 'border-box' }); } }, @@ -266,7 +266,7 @@ populateMessageBody = (oMessage, preload) => { oMessage = preload ? oMessage : null; let isNew = false, - json = oData && oData.Result, + json = oData?.Result, message = oMessage || MessageUserStore.message(); if ( diff --git a/dev/Component/AbstractInput.js b/dev/Component/AbstractInput.js index 63a8830db..b262fab22 100644 --- a/dev/Component/AbstractInput.js +++ b/dev/Component/AbstractInput.js @@ -12,7 +12,7 @@ export class AbstractInput { this.value = params.value || ''; this.label = params.label || ''; this.enable = null == params.enable ? true : params.enable; - this.trigger = params.trigger && params.trigger.subscribe ? params.trigger : null; + this.trigger = params.trigger?.subscribe ? params.trigger : null; this.placeholder = params.placeholder || ''; this.labeled = null != params.label; diff --git a/dev/Component/EmailAddresses.js b/dev/Component/EmailAddresses.js index afc294ad2..b176e5969 100644 --- a/dev/Component/EmailAddresses.js +++ b/dev/Component/EmailAddresses.js @@ -2,7 +2,7 @@ import { doc, createElement, addEventsListeners } from 'Common/Globals'; import { EmailModel } from 'Model/Email'; const contentType = 'snappymail/emailaddress', - getAddressKey = li => li && li.emailaddress && li.emailaddress.key; + getAddressKey = li => li?.emailaddress?.key; let dragAddress, datalist; @@ -19,7 +19,7 @@ export class EmailAddressesComponent { const self = this, // In Chrome we have no access to dataTransfer.getData unless it's the 'drop' event // In Chrome Mobile dataTransfer.types.includes(contentType) fails, only text/plain is set - validDropzone = () => dragAddress && dragAddress.li.parentNode !== self.ul, + validDropzone = () => dragAddress?.li.parentNode !== self.ul, fnDrag = e => validDropzone() && e.preventDefault(); self.element = element; @@ -116,7 +116,7 @@ export class EmailAddressesComponent { value, items => { self._resetDatalist(); - items && items.forEach(item => datalist.append(new Option(item))); + items?.forEach(item => datalist.append(new Option(item))); } ) } diff --git a/dev/External/User/ko.js b/dev/External/User/ko.js index a75a58d10..2ba6b78f7 100644 --- a/dev/External/User/ko.js +++ b/dev/External/User/ko.js @@ -14,8 +14,8 @@ const rlContentType = 'snappymail/action', // In Chrome we have no access to dataTransfer.getData unless it's the 'drop' event // In Chrome Mobile dataTransfer.types.includes(rlContentType) fails, only text/plain is set - dragMessages = () => dragData && 'messages' === dragData.action, - dragSortable = () => dragData && 'sortable' === dragData.action, + dragMessages = () => 'messages' === dragData?.action, + dragSortable = () => 'sortable' === dragData?.action, setDragAction = (e, action, effect, data, img) => { dragData = { action: action, @@ -45,8 +45,8 @@ Object.assign(ko.bindingHandlers, { let editor = null; const fValue = fValueAccessor(), - fUpdateEditorValue = () => fValue && fValue.__editor && fValue.__editor.setHtmlOrPlain(fValue()), - fUpdateKoValue = () => fValue && fValue.__editor && fValue(fValue.__editor.getDataWithHtmlMark()), + fUpdateEditorValue = () => fValue?.__editor?.setHtmlOrPlain(fValue()), + fUpdateKoValue = () => fValue?.__editor && fValue(fValue.__editor.getDataWithHtmlMark()), fOnReady = () => { fValue.__editor = editor; fUpdateEditorValue(); @@ -76,7 +76,7 @@ Object.assign(ko.bindingHandlers, { focused = fValue.focused; element.addresses = new EmailAddressesComponent(element, { - focusCallback: value => focused && focused(!!value), + focusCallback: value => focused?.(!!value), autoCompleteSource: fAllBindings.get('autoCompleteSource'), onChange: value => fValue(value) }); @@ -137,7 +137,7 @@ Object.assign(ko.bindingHandlers, { if (dragMessages()) { fnStop(e); element.classList.add('droppableHover'); - if (folder && folder.collapsed()) { + if (folder?.collapsed()) { dragTimer.start(() => { folder.collapsed(false); setExpandedFolder(folder.fullName, true); @@ -153,7 +153,7 @@ Object.assign(ko.bindingHandlers, { fnStop(e); if (dragMessages() && ['move','copy'].includes(e.dataTransfer.effectAllowed)) { let data = dragData.data; - if (folder && data && data.folder && isArray(data.uids)) { + if (folder && data?.folder && isArray(data.uids)) { moveMessagesToFolder(data.folder, data.uids, folder.fullName, data.copy && e.ctrlKey); } } @@ -220,7 +220,7 @@ Object.assign(ko.bindingHandlers, { options.list(arr); } dragData = null; - options.afterMove && options.afterMove(); + options.afterMove?.(); } } }); diff --git a/dev/External/ko.js b/dev/External/ko.js index dcdb5fa7d..7044ab55e 100644 --- a/dev/External/ko.js +++ b/dev/External/ko.js @@ -26,14 +26,14 @@ export const addSubscribablesTo = (target, subscribables) => forEachObjectEntry(subscribables, (key, fn) => target[key].subscribe(fn)), - dispose = disposable => disposable && isFunction(disposable.dispose) && disposable.dispose(), + dispose = disposable => isFunction(disposable?.dispose) && disposable.dispose(), // With this we don't need delegateRunOnDestroy koArrayWithDestroy = data => { data = ko.observableArray(data); data.subscribe(changes => changes.forEach(item => - 'deleted' === item.status && null == item.moved && item.value.onDestroy && item.value.onDestroy() + 'deleted' === item.status && null == item.moved && item.value.onDestroy?.() ) , data, 'arrayChange'); return data; @@ -172,12 +172,12 @@ ko.extenders.toggleSubscribeProperty = (target, options) => { const prop = options[1]; if (prop) { target.subscribe( - prev => prev && prev[prop] && prev[prop](false), + prev => prev?.[prop]?.(false), options[0], 'beforeChange' ); - target.subscribe(next => next && next[prop] && next[prop](true), options[0]); + target.subscribe(next => next?.[prop]?.(true), options[0]); } return target; diff --git a/dev/Knoin/AbstractModel.js b/dev/Knoin/AbstractModel.js index 95d0b2600..f98deade1 100644 --- a/dev/Knoin/AbstractModel.js +++ b/dev/Knoin/AbstractModel.js @@ -50,8 +50,7 @@ export class AbstractModel { // forEachObjectEntry(this, (key, value) => { forEachObjectValue(this, value => { /** clear CollectionModel */ - let arr = ko.isObservableArray(value) ? value() : value; - arr && arr.onDestroy && arr.onDestroy(); + (ko.isObservableArray(value) ? value() : value)?.onDestroy?.(); /** destroy ko.observable/ko.computed? */ // dispose(value); /** clear object value */ @@ -76,7 +75,7 @@ export class AbstractModel { */ static reviveFromJson(json) { let obj = this.validJson(json) ? new this() : null; - obj && obj.revivePropertiesFromJson(json); + obj?.revivePropertiesFromJson(json); return obj; } diff --git a/dev/Knoin/AbstractViews.js b/dev/Knoin/AbstractViews.js index 51ca41b72..d3722e216 100644 --- a/dev/Knoin/AbstractViews.js +++ b/dev/Knoin/AbstractViews.js @@ -128,7 +128,7 @@ export class AbstractViewSettings addSubscribablesTo(this, { [prop]: (value => { this[trigger](SaveSettingsStep.Animate); - valueCb && valueCb(value); + valueCb?.(value); rl.app.Remote.saveSetting(name, value, iError => { this[trigger](iError ? SaveSettingsStep.FalseResult : SaveSettingsStep.TrueResult); diff --git a/dev/Knoin/Knoin.js b/dev/Knoin/Knoin.js index 5196782f1..0ee9dba05 100644 --- a/dev/Knoin/Knoin.js +++ b/dev/Knoin/Knoin.js @@ -10,10 +10,7 @@ let defaultScreenName = ''; const - autofocus = dom => { - const af = dom.querySelector('[autofocus]'); - af && af.focus(); - }, + autofocus = dom => dom.querySelector('[autofocus]')?.focus(), visiblePopups = new Set, @@ -21,7 +18,7 @@ const * @param {string} screenName * @returns {?Object} */ - screen = screenName => screenName && null != SCREENS[screenName] ? SCREENS[screenName] : null, + screen = screenName => (screenName && SCREENS[screenName]) || null, /** * @param {Function} ViewModelClass @@ -77,10 +74,10 @@ const if (e.target === vmDom) { if (vmDom.classList.contains('animate')) { autofocus(vmDom); - vm.afterShow && vm.afterShow(); + vm.afterShow?.(); } else { vmDom.close(); - vm.afterHide && vm.afterHide(); + vm.afterHide?.(); } } }; @@ -101,7 +98,7 @@ const }); } else { visiblePopups.delete(vm); - vm.onHide && vm.onHide(); + vm.onHide?.(); vm.keyScope.unset(); vmDom.classList.remove('animate'); // trigger the transitions } @@ -118,7 +115,7 @@ const vm ); - vm.onBuild && vm.onBuild(vmDom); + vm.onBuild?.(vmDom); fireEvent('rl-view-model', vm); } else { @@ -142,10 +139,10 @@ const }, hideScreen = (screenToHide, destroy) => { - screenToHide.onHide && screenToHide.onHide(); + screenToHide.onHide?.(); forEachViewModel(screenToHide, (vm, dom) => { dom.hidden = true; - vm.onHide && vm.onHide(); + vm.onHide?.(); destroy && vm.viewModelDom.remove(); }); }, @@ -155,7 +152,7 @@ const * @returns {void} */ hideScreenPopup = ViewModelClassToHide => { - if (ViewModelClassToHide && ViewModelClassToHide.__vm && ViewModelClassToHide.__dom) { + if (ViewModelClassToHide?.__vm && ViewModelClassToHide?.__dom) { ViewModelClassToHide.__vm.modalVisible(false); } }, @@ -190,7 +187,7 @@ const } } - if (vmScreen && vmScreen.__started) { + if (vmScreen?.__started) { isSameScreen = currentScreen && vmScreen === currentScreen; if (!vmScreen.__builded) { @@ -200,7 +197,7 @@ const buildViewModel(ViewModelClass, vmScreen) ); - vmScreen.onBuild && vmScreen.onBuild(); + vmScreen.onBuild?.(); } setTimeout(() => { @@ -214,19 +211,19 @@ const // show screen if (!isSameScreen) { - vmScreen.onShow && vmScreen.onShow(); + vmScreen.onShow?.(); forEachViewModel(vmScreen, (vm, dom) => { - vm.beforeShow && vm.beforeShow(); + vm.beforeShow?.(); i18nToNodes(dom); dom.hidden = false; - vm.onShow && vm.onShow(); + vm.onShow?.(); autofocus(dom); }); } // -- - vmScreen.__cross && vmScreen.__cross.parse(subPart); + vmScreen.__cross?.parse(subPart); }, 1); } } @@ -248,11 +245,11 @@ export const if (vm) { params = params || []; - vm.beforeShow && vm.beforeShow(...params); + vm.beforeShow?.(...params); vm.modalVisible(true); - vm.onShow && vm.onShow(...params); + vm.onShow?.(...params); } }, @@ -295,7 +292,7 @@ export const const c = elementById('rl-content'), l = elementById('rl-loading'); c && (c.hidden = false); - l && l.remove(); + l?.remove(); }, /** diff --git a/dev/Model/AbstractCollection.js b/dev/Model/AbstractCollection.js index 85dd57449..919dc6154 100644 --- a/dev/Model/AbstractCollection.js +++ b/dev/Model/AbstractCollection.js @@ -12,7 +12,7 @@ export class AbstractCollectionModel extends Array } onDestroy() { - this.forEach(item => item.onDestroy && item.onDestroy()); + this.forEach(item => item.onDestroy?.()); } /** diff --git a/dev/Model/Email.js b/dev/Model/Email.js index 9edd51477..61b5ed2c5 100644 --- a/dev/Model/Email.js +++ b/dev/Model/Email.js @@ -283,7 +283,7 @@ export class EmailModel extends AbstractModel { */ static reviveFromJson(json) { const email = super.reviveFromJson(json); - email && email.clearDuplicateName(); + email?.clearDuplicateName(); return email; } @@ -351,7 +351,7 @@ export class EmailModel extends AbstractModel { ? new EmailModel(item.address.replace(/^[<]+(.*)[>]+$/g, '$1'), item.name || '') : null; - if (address && address.email) { + if (address?.email) { exists = true; } diff --git a/dev/Model/EmailCollection.js b/dev/Model/EmailCollection.js index a79feaa83..5e4744ef8 100644 --- a/dev/Model/EmailCollection.js +++ b/dev/Model/EmailCollection.js @@ -30,7 +30,7 @@ export class EmailCollectionModel extends AbstractCollectionModel toStringClear() { const result = []; this.forEach(email => { - if (email && email.email && email.name) { + if (email?.email && email?.name) { result.push(email.email); } }); diff --git a/dev/Model/FolderCollection.js b/dev/Model/FolderCollection.js index af05d3e2f..2a91f2b74 100644 --- a/dev/Model/FolderCollection.js +++ b/dev/Model/FolderCollection.js @@ -100,8 +100,8 @@ export const .post('Folders', FolderUserStore.foldersLoading) .then(data => { data = FolderCollectionModel.reviveFromJson(data.Result); - data && data.storeIt(); - fCallback && fCallback(true); + data?.storeIt(); + fCallback?.(true); // Repeat every 15 minutes? // this.foldersTimeout = setTimeout(loadFolders, 900000); }) @@ -128,7 +128,7 @@ export class FolderCollectionModel extends AbstractCollectionModel */ static reviveFromJson(object) { const expandedFolders = Local.get(ClientSideKeyNameExpandedFolders); - if (object && object.SystemFolders) { + if (object?.SystemFolders) { forEachObjectEntry(SystemFolders, key => SystemFolders[key] = SettingsGet(key+'Folder') || object.SystemFolders[FolderType[key]] ); diff --git a/dev/Model/Message.js b/dev/Model/Message.js index cdc27aad0..38ef408bb 100644 --- a/dev/Model/Message.js +++ b/dev/Model/Message.js @@ -323,7 +323,7 @@ export class MessageModel extends AbstractModel { */ fromDkimData() { let result = ['none', '']; - if (1 === arrayLength(this.from) && this.from[0] && this.from[0].dkimStatus) { + if (1 === arrayLength(this.from) && this.from[0]?.dkimStatus) { result = [this.from[0].dkimStatus, this.from[0].dkimValue || '']; } @@ -399,7 +399,7 @@ export class MessageModel extends AbstractModel { * @returns {string} */ fromAsSingleEmail() { - return isArray(this.from) && this.from[0] ? this.from[0].email : ''; + return (isArray(this.from) && this.from[0]?.email) || ''; } /** diff --git a/dev/Remote/AbstractFetch.js b/dev/Remote/AbstractFetch.js index 02c2d9efc..19046b364 100644 --- a/dev/Remote/AbstractFetch.js +++ b/dev/Remote/AbstractFetch.js @@ -136,7 +136,7 @@ export class AbstractFetchRemote undefined === iTimeout ? 30000 : pInt(iTimeout), data => { let cached = false; - if (data && data.Time) { + if (data?.Time) { cached = pInt(data.Time) > Date.now() - start; } @@ -162,7 +162,7 @@ export class AbstractFetchRemote } } - fCallback && fCallback( + fCallback?.( iError, data, cached, @@ -173,7 +173,7 @@ export class AbstractFetchRemote ) .catch(err => { console.error({fetchError:err}); - fCallback && fCallback( + fCallback?.( 'TimeoutError' == err.reason ? 3 : (err.name == 'AbortError' ? 2 : 1), err ); @@ -191,7 +191,7 @@ export class AbstractFetchRemote if (trigger) { value = !!value; (isArray(trigger) ? trigger : [trigger]).forEach(fTrigger => { - fTrigger && fTrigger(value); + fTrigger?.(value); }); } } @@ -207,12 +207,12 @@ export class AbstractFetchRemote } /* let isCached = false, type = ''; - if (data && data.Time) { + if (data?.Time) { isCached = pInt(data.Time) > microtime() - start; } // backward capability switch (true) { - case 'success' === textStatus && data && data.Result && action === data.Action: + case 'success' === textStatus && data?.Result && action === data.Action: type = AbstractFetchRemote.SUCCESS; break; case 'abort' === textStatus && (!data || !data.__aborted__): diff --git a/dev/Remote/User/Fetch.js b/dev/Remote/User/Fetch.js index b8d00ad62..4eab1b392 100644 --- a/dev/Remote/User/Fetch.js +++ b/dev/Remote/User/Fetch.js @@ -24,13 +24,13 @@ class RemoteUserFetch extends AbstractFetchRemote { const sFolderFullName = pString(params.Folder), folder = getFolderFromCacheList(sFolderFullName), - folderHash = (folder && folder.hash) || ''; + folderHash = folder?.hash || ''; params = Object.assign({ Offset: 0, Limit: SettingsUserStore.messagesPerPage(), Search: '', - UidNext: (folder && folder.uidNext) || 0, // Used to check for new messages + UidNext: folder?.uidNext || 0, // Used to check for new messages Sort: FolderUserStore.sortMode(), Hash: folderHash + SettingsGet('AccountHash') }, params); diff --git a/dev/Screen/AbstractSettings.js b/dev/Screen/AbstractSettings.js index 4619f21e4..57d1661b5 100644 --- a/dev/Screen/AbstractSettings.js +++ b/dev/Screen/AbstractSettings.js @@ -53,7 +53,7 @@ export class AbstractSettingsScreen extends AbstractScreen { settingsScreen ); - settingsScreen.onBuild && settingsScreen.onBuild(viewModelDom); + settingsScreen.onBuild?.(viewModelDom); } else { console.log('Cannot find sub settings view model position: SettingsSubScreen'); } @@ -67,10 +67,10 @@ export class AbstractSettingsScreen extends AbstractScreen { this.oCurrentSubScreen = settingsScreen; // show - settingsScreen.beforeShow && settingsScreen.beforeShow(); + settingsScreen.beforeShow?.(); i18nToNodes(settingsScreen.viewModelDom); settingsScreen.viewModelDom.hidden = false; - settingsScreen.onShow && settingsScreen.onShow(); + settingsScreen.onShow?.(); this.menu.forEach(item => { item.selected( @@ -90,7 +90,7 @@ export class AbstractSettingsScreen extends AbstractScreen { onHide() { let subScreen = this.oCurrentSubScreen; if (subScreen) { - subScreen.onHide && subScreen.onHide(); + subScreen.onHide?.(); subScreen.viewModelDom.hidden = true; } } diff --git a/dev/Screen/User/MailBox.js b/dev/Screen/User/MailBox.js index b40134792..a6f3f0054 100644 --- a/dev/Screen/User/MailBox.js +++ b/dev/Screen/User/MailBox.js @@ -95,7 +95,7 @@ export class MailBoxUserScreen extends AbstractScreen { /* // Disabled in SystemDropDown.html const email = AccountUserStore.email(); AccountUserStore.accounts.forEach(item => - item && email === item.email && item.count(e.detail) + email === item?.email && item?.count(e.detail) ); */ this.updateWindowTitle(); diff --git a/dev/Settings/User/Accounts.js b/dev/Settings/User/Accounts.js index 014d0be73..590bc3aa1 100644 --- a/dev/Settings/User/Accounts.js +++ b/dev/Settings/User/Accounts.js @@ -30,7 +30,7 @@ export class UserSettingsAccounts /*extends AbstractViewSettings*/ { } editAccount(account) { - if (account && account.isAdditional()) { + if (account?.isAdditional()) { showScreenPopup(AccountPopupView, [account]); } } @@ -48,7 +48,7 @@ export class UserSettingsAccounts /*extends AbstractViewSettings*/ { * @returns {void} */ deleteAccount(accountToRemove) { - if (accountToRemove && accountToRemove.askDelete()) { + if (accountToRemove?.askDelete()) { this.accountForDeletion(null); if (accountToRemove) { this.accounts.remove((account) => accountToRemove === account); @@ -72,7 +72,7 @@ export class UserSettingsAccounts /*extends AbstractViewSettings*/ { * @returns {void} */ deleteIdentity(identityToRemove) { - if (identityToRemove && identityToRemove.askDelete()) { + if (identityToRemove?.askDelete()) { this.identityForDeletion(null); if (identityToRemove) { diff --git a/dev/Settings/User/Filters.js b/dev/Settings/User/Filters.js index dd2e1bf63..e43ef044e 100644 --- a/dev/Settings/User/Filters.js +++ b/dev/Settings/User/Filters.js @@ -50,6 +50,6 @@ export class UserSettingsFilters /*extends AbstractViewSettings*/ { } onShow() { - window.Sieve && window.Sieve.updateList(); + window.Sieve?.updateList(); } } diff --git a/dev/Settings/User/Themes.js b/dev/Settings/User/Themes.js index 5e61f8b97..38676a770 100644 --- a/dev/Settings/User/Themes.js +++ b/dev/Settings/User/Themes.js @@ -74,7 +74,7 @@ export class UserSettingsThemes /*extends AbstractViewSettings*/ { .on('onComplete', (id, result, data) => { themeBackground.loading(false); - if (result && id && data && data.Result && data.Result.Name && data.Result.Hash) { + if (result && id && data?.Result?.Name && data?.Result?.Hash) { themeBackground.name(data.Result.Name); themeBackground.hash(data.Result.Hash); } else { @@ -94,11 +94,7 @@ export class UserSettingsThemes /*extends AbstractViewSettings*/ { } } - if (!errorMsg && data.ErrorMessage) { - errorMsg = data.ErrorMessage; - } - - themeBackground.error(errorMsg || i18n('SETTINGS_THEMES/ERROR_UNKNOWN')); + themeBackground.error(errorMsg || data.ErrorMessage || i18n('SETTINGS_THEMES/ERROR_UNKNOWN')); } return true; diff --git a/dev/Sieve/View/Filter.js b/dev/Sieve/View/Filter.js index cf5a2a03a..d541a584e 100644 --- a/dev/Sieve/View/Filter.js +++ b/dev/Sieve/View/Filter.js @@ -13,8 +13,7 @@ import { const // import { defaultOptionsAfterRender } from 'Common/Utils'; defaultOptionsAfterRender = (domItem, item) => - domItem && item && undefined !== item.disabled - && domItem.classList.toggle('disabled', domItem.disabled = item.disabled), + item && undefined !== item.disabled && domItem?.classList.toggle('disabled', domItem.disabled = item.disabled), // import { folderListOptionsBuilder } from 'Common/Folders'; /** diff --git a/dev/Stores/Admin/Package.js b/dev/Stores/Admin/Package.js index 3f4136338..19ddf9705 100644 --- a/dev/Stores/Admin/Package.js +++ b/dev/Stores/Admin/Package.js @@ -22,7 +22,7 @@ PackageAdminStore.fetch = () => { const loading = {}; PackageAdminStore.forEach(item => { - if (item && item.loading()) { + if (item?.loading()) { loading[item.file] = item; } }); diff --git a/dev/Stores/User/App.js b/dev/Stores/User/App.js index a38880570..6315b6e61 100644 --- a/dev/Stores/User/App.js +++ b/dev/Stores/User/App.js @@ -21,6 +21,6 @@ AppUserStore.focusedState.subscribe(value => { ThemeStore.isMobile() && leftPanelDisabled('FolderList' !== value); } let dom = elementById('V-Mail'+name); - dom && dom.classList.toggle('focused', name === value); + dom?.classList.toggle('focused', name === value); }); }); diff --git a/dev/Stores/User/Contact.js b/dev/Stores/User/Contact.js index f9db211ae..28ec7c5ed 100644 --- a/dev/Stores/User/Contact.js +++ b/dev/Stores/User/Contact.js @@ -33,12 +33,12 @@ ContactUserStore.sync = fResultFunc => { line = JSON.parse(line); if ('ContactsSync' === line.Action) { ContactUserStore.syncing(false); - fResultFunc && fResultFunc(line.ErrorCode, line); + fResultFunc?.(line.ErrorCode, line); } } catch (e) { ContactUserStore.syncing(false); console.error(e); - fResultFunc && fResultFunc(Notification.UnknownError); + fResultFunc?.(Notification.UnknownError); } }, 'ContactsSync'); } diff --git a/dev/Stores/User/Folder.js b/dev/Stores/User/Folder.js index 6f7534850..aec4bf758 100644 --- a/dev/Stores/User/Folder.js +++ b/dev/Stores/User/Folder.js @@ -80,15 +80,9 @@ export const FolderUserStore = new class { const subscribeRemoveSystemFolder = observable => { - observable.subscribe(() => { - const folder = getFolderFromCacheList(observable()); - folder && folder.type(FolderType.User); - }, self, 'beforeChange'); + observable.subscribe(() => getFolderFromCacheList(observable())?.type(FolderType.User), self, 'beforeChange'); }, - fSetSystemFolderType = type => value => { - const folder = getFolderFromCacheList(value); - folder && folder.type(type); - }; + fSetSystemFolderType = type => value => getFolderFromCacheList(value)?.type(type); subscribeRemoveSystemFolder(self.sentFolder); subscribeRemoveSystemFolder(self.draftsFolder); @@ -134,8 +128,7 @@ export const FolderUserStore = new class { fSearchFunction = (list) => { list.forEach(folder => { if ( - folder && - folder.selectable() && + folder?.selectable() && folder.exists && timeout > folder.expires && (folder.isSystemFolder() || (folder.isSubscribed() && (folder.checkable() || !bDisplaySpecSetting))) @@ -143,7 +136,7 @@ export const FolderUserStore = new class { timeouts.push([folder.expires, folder.fullName]); } - if (folder && folder.subFolders.length) { + if (folder?.subFolders.length) { fSearchFunction(folder.subFolders()); } }); diff --git a/dev/Stores/User/GnuPG.js b/dev/Stores/User/GnuPG.js index 6352c8789..248880588 100644 --- a/dev/Stores/User/GnuPG.js +++ b/dev/Stores/User/GnuPG.js @@ -38,7 +38,7 @@ export const GnuPGUserStore = new class { this.privateKeys([]); Remote.request('GnupgGetKeys', (iError, oData) => { - if (oData && oData.Result) { + if (oData?.Result) { this.keyring = oData.Result; const initKey = (key, isPrivate) => { const aEmails = []; @@ -73,7 +73,7 @@ export const GnuPGUserStore = new class { key.view = () => { const fetch = pass => Remote.request('GnupgExportKey', (iError, oData) => { - if (oData && oData.Result) { + if (oData?.Result) { key.armor = oData.Result; showScreenPopup(OpenPgpKeyPopupView, [key]); } @@ -111,10 +111,10 @@ export const GnuPGUserStore = new class { importKey(key, callback) { Remote.request('GnupgImportKey', (iError, oData) => { - if (oData && oData.Result/* && (oData.Result.imported || oData.Result.secretimported)*/) { + if (oData?.Result/* && (oData.Result.imported || oData.Result.secretimported)*/) { this.loadKeyrings(); } - callback && callback(iError, oData); + callback?.(iError, oData); }, { Key: key } @@ -131,10 +131,10 @@ export const GnuPGUserStore = new class { storeKeyPair(keyPair, callback) { Remote.request('PgpStoreKeyPair', (iError, oData) => { - if (oData && oData.Result) { + if (oData?.Result) { // this.gnupgKeyring = oData.Result; } - callback && callback(iError, oData); + callback?.(iError, oData); }, keyPair ); } @@ -187,7 +187,7 @@ export const GnuPGUserStore = new class { } if (null !== params.Passphrase) { const result = await Remote.post('GnupgDecrypt', null, params); - if (result && result.Result) { + if (result?.Result) { return result.Result; } } @@ -208,7 +208,7 @@ export const GnuPGUserStore = new class { data.SigPart = data.SigPart.body; } let response = await Remote.post('MessagePgpVerify', null, data); - if (response && response.Result) { + if (response?.Result) { return { fingerprint: response.Result.fingerprint, success: 0 == response.Result.status // GOODSIG diff --git a/dev/Stores/User/Message.js b/dev/Stores/User/Message.js index e6c44d530..a012f03d1 100644 --- a/dev/Stores/User/Message.js +++ b/dev/Stores/User/Message.js @@ -42,7 +42,7 @@ export const MessageUserStore = new class { purgeMessageBodyCache() { const messagesDom = this.bodiesDom(), - children = messagesDom && messagesDom.children; + children = messagesDom?.children; if (children) { while (15 < children.length) { children[0].remove(); diff --git a/dev/Stores/User/Messagelist.js b/dev/Stores/User/Messagelist.js index 2bc7cbcc5..20fee8a71 100644 --- a/dev/Stores/User/Messagelist.js +++ b/dev/Stores/User/Messagelist.js @@ -270,8 +270,7 @@ MessagelistUserStore.setAction = (sFolderFullName, iSetAction, messages) => { let folder, alreadyUnread = 0, - rootUids = messages.map(oMessage => oMessage && oMessage.uid ? oMessage.uid : null) - .validUnique(), + rootUids = messages.map(oMessage => oMessage?.uid).validUnique(), length = rootUids.length; if (sFolderFullName && length) { @@ -333,7 +332,7 @@ MessagelistUserStore.removeMessagesFromList = ( ? messageList.filter(item => item && uidForRemove.includes(pInt(item.uid))) : []; - messages.forEach(item => item && item.isUnseen() && ++unseenCount); + messages.forEach(item => item?.isUnseen() && ++unseenCount); if (fromFolder) { fromFolder.hash = ''; @@ -387,7 +386,7 @@ MessagelistUserStore.removeMessagesFromList = ( if (MessagelistUserStore.threadUid()) { if ( messageList.length && - messageList.find(item => item && item.deleted() && item.uid == MessagelistUserStore.threadUid()) + messageList.find(item => item?.deleted() && item.uid == MessagelistUserStore.threadUid()) ) { const message = messageList.find(item => item && !item.deleted()); let setHash; diff --git a/dev/Stores/User/Notification.js b/dev/Stores/User/Notification.js index 403460caa..0ad7d28e8 100644 --- a/dev/Stores/User/Notification.js +++ b/dev/Stores/User/Notification.js @@ -6,7 +6,7 @@ import { fireEvent } from 'Common/Globals'; * Might not work due to the new ServiceWorkerRegistration.showNotification */ const HTML5Notification = window.Notification, - HTML5NotificationStatus = () => (HTML5Notification && HTML5Notification.permission) || 'denied', + HTML5NotificationStatus = () => HTML5Notification?.permission || 'denied', NotificationsDenied = () => 'denied' === HTML5NotificationStatus(), NotificationsGranted = () => 'granted' === HTML5NotificationStatus(), dispatchMessage = data => { @@ -26,7 +26,7 @@ if (WorkerNotifications && ServiceWorkerRegistration && ServiceWorkerRegistratio /* Listen for close requests from the ServiceWorker */ WorkerNotifications.addEventListener('message', event => { const obj = JSON.parse(event.data); - obj && 'notificationclick' === obj.action && dispatchMessage(obj.data); + 'notificationclick' === obj?.action && dispatchMessage(obj.data); }); } else { WorkerNotifications = null; @@ -60,7 +60,7 @@ export const NotificationUserStore = new class { icon: imageSrc || Links.staticLink('css/images/icon-message-notification.png'), data: messageData }; - if (messageData && messageData.Uid) { + if (messageData?.Uid) { options.tag = messageData.Uid; } if (WorkerNotifications) { @@ -83,7 +83,7 @@ export const NotificationUserStore = new class { .catch(e => console.error(e)); } else { const notification = new HTML5Notification(title, options); - notification.show && notification.show(); + notification.show?.(); notification.onclick = messageData ? () => dispatchMessage(messageData) : null; setTimeout(() => notification.close(), 7000); } diff --git a/dev/Stores/User/OpenPGP.js b/dev/Stores/User/OpenPGP.js index 652537fe8..be15ac2e4 100644 --- a/dev/Stores/User/OpenPGP.js +++ b/dev/Stores/User/OpenPGP.js @@ -196,7 +196,7 @@ export const OpenPGPUserStore = new class { const publicKey = findOpenPGPKey(this.publicKeys, sender/*, sign*/); return await openpgp.decrypt({ message, - verificationKeys: publicKey && publicKey.key, + verificationKeys: publicKey?.key, // expectSigned: true, // signature: '', // Detached signature decryptionKeys: decryptedKey diff --git a/dev/Stores/User/Pgp.js b/dev/Stores/User/Pgp.js index b5291e851..f21a1cfe9 100644 --- a/dev/Stores/User/Pgp.js +++ b/dev/Stores/User/Pgp.js @@ -169,7 +169,7 @@ export const } ); if (result) { - if (result.error && result.error.message) { + if (result.error?.message) { if ('PWD_DIALOG_CANCEL' !== result.error.code) { alert(result.error.code + ': ' + result.error.message); } diff --git a/dev/View/Popup/Account.js b/dev/View/Popup/Account.js index 71e8ab12e..6117803fa 100644 --- a/dev/View/Popup/Account.js +++ b/dev/View/Popup/Account.js @@ -38,7 +38,7 @@ export class AccountPopupView extends AbstractViewPopup { this.submitRequest(false); if (iError) { this.submitError(getNotification(iError)); - this.submitErrorAdditional((data && data.ErrorMessageAdditional) || ''); + this.submitErrorAdditional(data?.ErrorMessageAdditional); } else { rl.app.accountsAndIdentities(); this.close(); @@ -54,7 +54,7 @@ export class AccountPopupView extends AbstractViewPopup { } onShow(account) { - if (account && account.isAdditional()) { + if (account?.isAdditional()) { this.isNew(false); this.email(account.email); } else { diff --git a/dev/View/Popup/Compose.js b/dev/View/Popup/Compose.js index 065792db1..1f56d11b1 100644 --- a/dev/View/Popup/Compose.js +++ b/dev/View/Popup/Compose.js @@ -213,8 +213,8 @@ export class ComposePopupView extends AbstractViewPopup { super('Compose'); const fEmailOutInHelper = (context, identity, name, isIn) => { - if (identity && context && identity[name]() && (isIn ? true : context[name]())) { - const identityEmail = identity[name](); + const identityEmail = context && identity?.[name](); + if (identityEmail && (isIn ? true : context[name]())) { let list = context[name]().trim().split(','); list = list.filter(email => { @@ -222,9 +222,7 @@ export class ComposePopupView extends AbstractViewPopup { return email && identityEmail.trim() !== email; }); - if (isIn) { - list.push(identityEmail); - } + isIn && list.push(identityEmail); context[name](list.join(',')); } @@ -355,7 +353,7 @@ export class ComposePopupView extends AbstractViewPopup { }, attachmentsInProcess: () => this.attachments.filter(item => item && !item.complete()), - attachmentsInError: () => this.attachments.filter(item => item && item.error()), + attachmentsInError: () => this.attachments.filter(item => item?.error()), attachmentsCount: () => this.attachments.length, attachmentsInErrorCount: () => this.attachmentsInError.length, @@ -511,7 +509,7 @@ export class ComposePopupView extends AbstractViewPopup { alternative.children.push(data); data = alternative; } - if (sign && !draft && sign[1]) { + if (!draft && sign?.[1]) { if ('openpgp' == sign[0]) { // Doesn't sign attachments params.Html = params.Text = ''; @@ -611,7 +609,7 @@ export class ComposePopupView extends AbstractViewPopup { this.savedErrorDesc(i18n('COMPOSE/SAVED_ERROR_ON_SEND').trim()); } else { this.sendError(true); - this.sendErrorDesc(getNotification(iError, data && data.ErrorMessage) + this.sendErrorDesc(getNotification(iError, data?.ErrorMessage) || getNotification(Notification.CantSendMessage)); } } else { @@ -762,7 +760,7 @@ export class ComposePopupView extends AbstractViewPopup { (iError, data) => { if (!iError && isArray(data.Result)) { fResponse( - data.Result.map(item => (item && item[0] ? (new EmailModel(item[0], item[1])).toLine() : null)) + data.Result.map(item => (item?.[0] ? (new EmailModel(item[0], item[1])).toLine() : null)) .filter(v => v) ); } else if (Notification.RequestAborted !== iError) { @@ -777,7 +775,7 @@ export class ComposePopupView extends AbstractViewPopup { } selectIdentity(identity) { - identity = identity && identity.item; + identity = identity?.item; if (identity) { this.currentIdentity(identity); this.setSignatureFromIdentity(identity); @@ -1153,7 +1151,7 @@ export class ComposePopupView extends AbstractViewPopup { }); } else { this.attachments.forEach(attachment => { - if (attachment && attachment.fromMessage) { + if (attachment?.fromMessage) { attachment .waiting(false) .uploading(false) @@ -1180,7 +1178,7 @@ export class ComposePopupView extends AbstractViewPopup { if (!this.to()) { this.to.focused(true); } else if (!this.to.focused()) { - this.oEditor && this.oEditor.focus(); + this.oEditor?.focus(); } }, 100); } @@ -1266,7 +1264,7 @@ export class ComposePopupView extends AbstractViewPopup { }) .on('onComplete', (id, result, data) => { const attachment = this.getAttachmentById(id), - response = (data && data.Result) || {}, + response = data?.Result || {}, errorCode = response.ErrorCode, attachmentJson = result && response.Attachment; @@ -1354,7 +1352,7 @@ export class ComposePopupView extends AbstractViewPopup { prepareAttachmentsForSendOrSave() { const result = {}; this.attachments.forEach(item => { - if (item && item.complete() && item.tempName() && item.enabled()) { + if (item?.complete() && item?.tempName() && item?.enabled()) { result[item.tempName()] = [item.fileName(), item.isInline ? '1' : '0', item.CID, item.contentLocation]; } }); @@ -1381,7 +1379,7 @@ export class ComposePopupView extends AbstractViewPopup { oJua || attachment.waiting(false).uploading(true); attachment.cancel = () => { this.attachments.remove(attachment); - oJua && oJua.cancel(attachment.id); + oJua?.cancel(attachment.id); }; this.attachments.push(attachment); view && this.attachmentsArea(); @@ -1435,7 +1433,7 @@ export class ComposePopupView extends AbstractViewPopup { isEmptyForm(includeAttachmentInProgress = true) { const withoutAttachment = includeAttachmentInProgress ? !this.attachments.length - : !this.attachments.some(item => item && item.complete()); + : !this.attachments.some(item => item?.complete()); return ( !this.to.length && @@ -1491,7 +1489,7 @@ export class ComposePopupView extends AbstractViewPopup { this.sending(false); this.saving(false); - this.oEditor && this.oEditor.clear(); + this.oEditor?.clear(); this.dropMailvelope(); } diff --git a/dev/View/Popup/Contacts.js b/dev/View/Popup/Contacts.js index 443935390..e727870eb 100644 --- a/dev/View/Popup/Contacts.js +++ b/dev/View/Popup/Contacts.js @@ -108,7 +108,7 @@ export class ContactsPopupView extends AbstractViewPopup { contactHasValidName: () => !!this.viewProperties.find(prop => propertyIsName(prop) && prop.isValid()), contactsCheckedOrSelected: () => { - const checked = ContactUserStore.filter(item => item.checked && item.checked()), + const checked = ContactUserStore.filter(item => item.checked?.()), selected = this.currentContact(); return selected @@ -120,7 +120,7 @@ export class ContactsPopupView extends AbstractViewPopup { contactsSyncEnabled: () => ContactUserStore.allowSync() && ContactUserStore.syncMode(), - viewHash: () => '' + this.viewProperties.map(property => property.value && property.value()).join('') + viewHash: () => '' + this.viewProperties.map(property => property.value?.()).join('') }); this.search.subscribe(() => this.reloadContactList()); @@ -164,7 +164,7 @@ export class ContactsPopupView extends AbstractViewPopup { const data = oItem.getNameAndEmailHelper(), email = data ? new EmailModel(data[0], data[1]) : null; - if (email && email.validate()) { + if (email?.validate()) { return email; } } @@ -344,7 +344,7 @@ export class ContactsPopupView extends AbstractViewPopup { if (this.contactsCheckedOrSelected().length) { Remote.request('ContactsDelete', (iError, oData) => { - if (500 < (!iError && oData && oData.Time ? pInt(oData.Time) : 0)) { + if (500 < (!iError && oData?.Time) ? pInt(oData.Time) : 0) { this.reloadContactList(this.bDropPageAfterDelete); } else { setTimeout(() => this.reloadContactList(this.bDropPageAfterDelete), 500); diff --git a/dev/View/Popup/Domain.js b/dev/View/Popup/Domain.js index 258f4552b..d5bc6151b 100644 --- a/dev/View/Popup/Domain.js +++ b/dev/View/Popup/Domain.js @@ -248,7 +248,7 @@ export class DomainPopupView extends AbstractViewPopup { if (oDomain) { this.enableSmartPorts(false); this.edit(true); - forEachObjectEntry(oDomain, (key, value) => this[key] && this[key](value)); + forEachObjectEntry(oDomain, (key, value) => this[key]?.(value)); this.enableSmartPorts(true); } } diff --git a/dev/View/Popup/Identity.js b/dev/View/Popup/Identity.js index dcdbde8bc..2972f7ad8 100644 --- a/dev/View/Popup/Identity.js +++ b/dev/View/Popup/Identity.js @@ -63,9 +63,7 @@ export class IdentityPopupView extends AbstractViewPopup { submitForm() { if (!this.submitRequest()) { - if (this.signature && this.signature.__fetchEditorValue) { - this.signature.__fetchEditorValue(); - } + this.signature?.__fetchEditorValue?.(); if (!this.emailHasError()) { this.emailHasError(!this.email().trim()); diff --git a/dev/View/Popup/Languages.js b/dev/View/Popup/Languages.js index ff62f63e3..f7d33327c 100644 --- a/dev/View/Popup/Languages.js +++ b/dev/View/Popup/Languages.js @@ -51,7 +51,7 @@ export class LanguagesPopupView extends AbstractViewPopup { } changeLanguage(lang) { - this.fLang && this.fLang(lang); + this.fLang?.(lang); this.close(); } } diff --git a/dev/View/Popup/OpenPgpGenerate.js b/dev/View/Popup/OpenPgpGenerate.js index 6d50d8dd8..0b392c586 100644 --- a/dev/View/Popup/OpenPgpGenerate.js +++ b/dev/View/Popup/OpenPgpGenerate.js @@ -94,7 +94,7 @@ export class OpenPgpGeneratePopupView extends AbstractViewPopup { showError(e) { console.log(e); - if (e && e.message) { + if (e?.message) { this.submitError(e.message); } } diff --git a/dev/View/User/Login.js b/dev/View/User/Login.js index 51eb9aed6..03066afb0 100644 --- a/dev/View/User/Login.js +++ b/dev/View/User/Login.js @@ -114,9 +114,9 @@ export class LoginUserView extends AbstractViewLogin { if (Notification.InvalidInputArgument == iError) { iError = Notification.AuthError; } - this.submitError(getNotification(iError, (oData ? oData.ErrorMessage : ''), + this.submitError(getNotification(iError, oData?.ErrorMessage, Notification.UnknownNotification)); - this.submitErrorAdditional((oData && oData.ErrorMessageAdditional) || ''); + this.submitErrorAdditional(oData?.ErrorMessageAdditional); } else { rl.setData(oData.Result); } diff --git a/dev/View/User/MailBox/FolderList.js b/dev/View/User/MailBox/FolderList.js index cc6345827..113f3d98d 100644 --- a/dev/View/User/MailBox/FolderList.js +++ b/dev/View/User/MailBox/FolderList.js @@ -82,7 +82,7 @@ export class MailFolderList extends AbstractViewLeft { } el = eqs(event, 'a'); - if (el && el.matches('.selectable')) { + if (el?.matches('.selectable')) { event.preventDefault(); const folder = ko.dataFor(el); if (folder) { @@ -170,10 +170,10 @@ export class MailFolderList extends AbstractViewLeft { AppUserStore.focusedState.subscribe(value => { let el = qs('li a.focused'); - el && el.classList.remove('focused'); + el?.classList.remove('focused'); if (Scope.FolderList === value) { el = qs('li a.selected'); - el && el.classList.add('focused'); + el?.classList.add('focused'); } }); } diff --git a/dev/View/User/MailBox/MessageList.js b/dev/View/User/MailBox/MessageList.js index 2ca3705d8..d94831820 100644 --- a/dev/View/User/MailBox/MessageList.js +++ b/dev/View/User/MailBox/MessageList.js @@ -210,7 +210,7 @@ export class MailMessageList extends AbstractViewRight { const sFolder = e.detail.Folder, iUid = e.detail.Uid; const message = MessagelistUserStore.find( - item => item && sFolder === item.folder && iUid == item.uid + item => sFolder === item?.folder && iUid == item?.uid ); if ('INBOX' === sFolder) { @@ -326,7 +326,7 @@ export class MailMessageList extends AbstractViewRight { moveNewCommand(vm, event) { if (this.newMoveToFolder && this.mobileCheckedStateShow()) { - if (vm && event && event.preventDefault) { + if (vm && event?.preventDefault) { event.preventDefault(); event.stopPropagation(); } @@ -428,7 +428,7 @@ export class MailMessageList extends AbstractViewRight { getDragData(event) { const item = ko.dataFor(doc.elementFromPoint(event.clientX, event.clientY)); - item && item.checked && item.checked(true); + item?.checked?.(true); const uids = MessagelistUserStore.listCheckedOrSelectedUidsWithSubMails(); item && !uids.includes(item.uid) && uids.push(item.uid); return uids.length ? { @@ -571,7 +571,7 @@ export class MailMessageList extends AbstractViewRight { } gotoThread(message) { - if (message && 0 < message.threadsLen()) { + if (0 < message?.threadsLen()) { MessagelistUserStore.pageBeforeThread(MessagelistUserStore.page()); hasher.setHash( @@ -718,7 +718,7 @@ export class MailMessageList extends AbstractViewRight { registerShortcut('t', '', [Scope.MessageList], () => { let message = MessagelistUserStore.selectedMessage() || MessagelistUserStore.focusedMessage(); - if (message && 0 < message.threadsLen()) { + if (0 < message?.threadsLen()) { this.gotoThread(message); } return false; diff --git a/dev/View/User/MailBox/MessageView.js b/dev/View/User/MailBox/MessageView.js index 3cfa04522..20b4d7613 100644 --- a/dev/View/User/MailBox/MessageView.js +++ b/dev/View/User/MailBox/MessageView.js @@ -134,8 +134,8 @@ export class MailMessageView extends AbstractViewRight { allowAttachmentControls: () => arrayLength(attachmentsActions) && SettingsCapa('AttachmentsActions'), downloadAsZipAllowed: () => this.attachmentsActions.includes('zip') - && (currentMessage() ? currentMessage().attachments : []) - .filter(item => item && !item.isLinked() && item.checked() && item.download) + && (currentMessage()?.attachments || []) + .filter(item => item?.download && !item?.isLinked() && item?.checked()) .length, tagsAllowed: () => FolderUserStore.currentFolder() ? FolderUserStore.currentFolder().tagsAllowed() : false, @@ -286,7 +286,7 @@ export class MailMessageView extends AbstractViewRight { el = eqs(event, '.attachmentsPlace .attachmentItem .attachmentNameParent'); if (el) { const attachment = ko.dataFor(el); - if (attachment && attachment.linkDownload()) { + if (attachment?.linkDownload()) { if ('message/rfc822' == attachment.mimeType) { // TODO rl.fetch(attachment.linkDownload()).then(response => { @@ -393,7 +393,7 @@ export class MailMessageView extends AbstractViewRight { // toggle message blockquotes registerShortcut('b', '', [Scope.MessageList, Scope.MessageView], () => { const message = currentMessage(); - if (message && message.body) { + if (message?.body) { message.body.querySelectorAll('.rlBlockquoteSwitcher').forEach(node => node.click()); return false; } @@ -411,7 +411,7 @@ export class MailMessageView extends AbstractViewRight { // print addShortcut('p,printscreen', 'meta', [Scope.MessageView, Scope.MessageList], () => { - currentMessage() && currentMessage().printMessage(); + currentMessage()?.printMessage(); return false; }); @@ -510,7 +510,7 @@ export class MailMessageView extends AbstractViewRight { downloadAsZip() { const hashes = (currentMessage() ? currentMessage().attachments : []) - .map(item => (item && !item.isLinked() && item.checked() ? item.download : '')) + .map(item => item?.checked() && !item?.isLinked() ? item.download : '') .filter(v => v); if (hashes.length) { Remote.post('AttachmentsActions', this.downloadAsZipLoading, { @@ -518,7 +518,7 @@ export class MailMessageView extends AbstractViewRight { Hashes: hashes }) .then(result => { - let hash = result && result.Result && result.Result.FileHash; + let hash = result?.Result?.FileHash; if (hash) { download(attachmentDownload(hash), hash+'.zip'); } else { @@ -577,7 +577,7 @@ export class MailMessageView extends AbstractViewRight { if (result.data) { MimeToMessage(result.data, oMessage); oMessage.html() ? oMessage.viewHtml() : oMessage.viewPlain(); - if (result.signatures && result.signatures.length) { + if (result.signatures?.length) { oMessage.pgpSigned(true); oMessage.pgpVerified({ signatures: result.signatures, @@ -596,7 +596,7 @@ export class MailMessageView extends AbstractViewRight { oMessage.pgpVerified(result); } /* - if (result && result.success) { + if (result?.success) { i18n('OPENPGP/GOOD_SIGNATURE', { USER: validKey.user + ' (' + validKey.id + ')' }); @@ -604,7 +604,7 @@ export class MailMessageView extends AbstractViewRight { } else { const keyIds = arrayLength(signingKeyIds) ? signingKeyIds : null, additional = keyIds - ? keyIds.map(item => (item && item.toHex ? item.toHex() : null)).filter(v => v).join(', ') + ? keyIds.map(item => item?.toHex?.()).filter(v => v).join(', ') : ''; i18n('OPENPGP/ERROR', { diff --git a/dev/View/User/SystemDropDown.js b/dev/View/User/SystemDropDown.js index b56eefc53..b3e5560f1 100644 --- a/dev/View/User/SystemDropDown.js +++ b/dev/View/User/SystemDropDown.js @@ -52,7 +52,7 @@ export class SystemDropDownUserView extends AbstractViewRight { } accountClick(account, event) { - let email = account && account.email; + let email = account?.email; if (email && 0 === event.button && AccountUserStore.email() != email) { AccountUserStore.loading(true); event.preventDefault(); diff --git a/dev/dragdropgecko.js b/dev/dragdropgecko.js index 7013f8c5d..65836b5e9 100644 --- a/dev/dragdropgecko.js +++ b/dev/dragdropgecko.js @@ -70,7 +70,7 @@ htmlDrag = b => doc.documentElement.classList.toggle('firefox-drag', b), setDragImage = (src, xOffset, yOffset) => { - img && img.remove(); + img?.remove(); if (src) { // create drag image from custom element or drag source img = src.cloneNode(true); @@ -85,7 +85,7 @@ if (dragSource) { clearInterval(holdInterval); // dispose of drag image element - img && img.remove(); + img?.remove(); isDragging && dispatchEvent(lastTouch, 'dragend', dragSource); img = dragSource = lastTouch = lastTarget = dataTransfer = holdInterval = null; isDragging = allowDrop = false; diff --git a/dev/shortcuts.js b/dev/shortcuts.js index 794cfd2bf..0ff31b78d 100644 --- a/dev/shortcuts.js +++ b/dev/shortcuts.js @@ -64,9 +64,8 @@ const keydown = event => { let key = (event.key || '').toLowerCase().replace(' ','space'), modifiers = ['alt','ctrl','meta','shift'].filter(v => event[v+'Key']).join('+'); - scope[key] && scope[key][modifiers] && scope[key][modifiers].forEach(cmd => exec(event, cmd)); - !event.defaultPrevented && _scope !== 'all' && _scopes.all[key] && _scopes.all[key][modifiers] - && _scopes.all[key][modifiers].forEach(cmd => exec(event, cmd)); + scope[key]?.[modifiers]?.forEach(cmd => exec(event, cmd)); + !event.defaultPrevented && _scope !== 'all' && _scopes.all[key]?.[modifiers]?.forEach(cmd => exec(event, cmd)); }; win.shortcuts = shortcuts;