Use JavaScript Optional chaining

This commit is contained in:
the-djmaze 2022-09-02 11:52:07 +02:00
parent d9bc435e2c
commit 732b6eb641
55 changed files with 169 additions and 199 deletions

View file

@ -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');
}

View file

@ -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];
}
/**

View file

@ -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';
}

View file

@ -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) {

View file

@ -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),

View file

@ -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;
}

View file

@ -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;

View file

@ -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();

View file

@ -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);
},

View file

@ -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)))),

View file

@ -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 (

View file

@ -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;

View file

@ -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)));
}
)
}

View file

@ -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?.();
}
}
});

8
dev/External/ko.js vendored
View file

@ -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;

View file

@ -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;
}

View file

@ -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);

View file

@ -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();
},
/**

View file

@ -12,7 +12,7 @@ export class AbstractCollectionModel extends Array
}
onDestroy() {
this.forEach(item => item.onDestroy && item.onDestroy());
this.forEach(item => item.onDestroy?.());
}
/**

View file

@ -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;
}

View file

@ -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);
}
});

View file

@ -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]]
);

View file

@ -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) || '';
}
/**

View file

@ -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__):

View file

@ -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);

View file

@ -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;
}
}

View file

@ -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();

View file

@ -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) {

View file

@ -50,6 +50,6 @@ export class UserSettingsFilters /*extends AbstractViewSettings*/ {
}
onShow() {
window.Sieve && window.Sieve.updateList();
window.Sieve?.updateList();
}
}

View file

@ -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;

View file

@ -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';
/**

View file

@ -22,7 +22,7 @@ PackageAdminStore.fetch = () => {
const loading = {};
PackageAdminStore.forEach(item => {
if (item && item.loading()) {
if (item?.loading()) {
loading[item.file] = item;
}
});

View file

@ -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);
});
});

View file

@ -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');
}

View file

@ -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());
}
});

View file

@ -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

View file

@ -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();

View file

@ -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;

View file

@ -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);
}

View file

@ -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

View file

@ -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);
}

View file

@ -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 {

View file

@ -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();
}

View file

@ -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);

View file

@ -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);
}
}

View file

@ -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());

View file

@ -51,7 +51,7 @@ export class LanguagesPopupView extends AbstractViewPopup {
}
changeLanguage(lang) {
this.fLang && this.fLang(lang);
this.fLang?.(lang);
this.close();
}
}

View file

@ -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);
}
}

View file

@ -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);
}

View file

@ -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');
}
});
}

View file

@ -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;

View file

@ -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', {

View file

@ -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();

View file

@ -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;

View file

@ -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;