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