Small code cleanups and fix translations

This commit is contained in:
djmaze 2021-01-27 00:26:31 +01:00
parent b31bf3d7f5
commit 7ccc44616d
54 changed files with 288 additions and 426 deletions

View file

@ -113,25 +113,25 @@ RainLoop 1.14 vs SnappyMail
|js/* |RainLoop |Snappy |
|--------------- |--------: |--------: |
|admin.js |2.130.942 | 123.042 |
|app.js |4.184.455 | 534.334 |
|admin.js |2.130.942 | 120.785 |
|app.js |4.184.455 | 529.074 |
|boot.js | 671.522 | 4.842 |
|libs.js | 647.614 | 235.475 |
|polyfills.js | 325.834 | 0 |
|serviceworker.js | 0 | 285 |
|TOTAL |7.960.367 | 897.978 |
|TOTAL |7.960.367 | 890.449 |
|js/min/* |RainLoop |Snappy |Rain gzip |gzip |brotli |
|--------------- |--------: |--------: |--------: |--------: |--------: |
|admin.min.js | 252.147 | 63.913 | 73.657 | 18.158 | 16.135 |
|app.min.js | 511.202 | 262.917 |140.462 | 74.870 | 62.686 |
|admin.min.js | 252.147 | 62.863 | 73.657 | 18.009 | 15.992 |
|app.min.js | 511.202 | 259.534 |140.462 | 74.005 | 62.184 |
|boot.min.js | 66.007 | 2.630 | 22.567 | 1.375 | 1.189 |
|libs.min.js | 572.545 | 130.930 |176.720 | 47.397 | 42.116 |
|polyfills.min.js | 32.452 | 0 | 11.312 | 0 | 0 |
|TOTAL |1.434.353 | 460.390 |424.718 |141.800 |122.126 |
|TOTAL (no admin) |1.182.206 | 396.477 |351.061 |123.642 |105.991 |
|TOTAL |1.434.353 | 455.957 |424.718 |140.786 |121.481 |
|TOTAL (no admin) |1.182.206 | 393.094 |351.061 |122.777 |105.489 |
For a user its around 64% smaller and faster than traditional RainLoop.
For a user its around 65% smaller and faster than traditional RainLoop.
### CSS changes

View file

@ -1,9 +1,10 @@
import ko from 'ko';
import {
doc,
$htmlCL,
leftPanelDisabled,
leftPanelType
Settings
} from 'Common/Globals';
import { KeyState } from 'Common/Enums';
@ -11,7 +12,7 @@ import { rootAdmin, rootUser } from 'Common/Links';
import { initOnStartOrLangChange } from 'Common/Translator';
import LanguageStore from 'Stores/Language';
import ThemeStore from 'Stores/Theme';
import { ThemeStore } from 'Stores/Theme';
import SaveTriggerComponent from 'Component/SaveTrigger';
import InputComponent from 'Component/Input';
@ -20,8 +21,6 @@ import TextAreaComponent from 'Component/TextArea';
import CheckboxMaterialDesignComponent from 'Component/MaterialDesign/Checkbox';
import CheckboxComponent from 'Component/Checkbox';
const Settings = rl.settings, doc = document;
export class AbstractApp {
/**
* @param {RemoteStorage|AdminRemoteStorage} Remote
@ -45,16 +44,12 @@ export class AbstractApp {
return null;
}
data() {
return null;
}
/**
* @param {string} link
* @returns {boolean}
*/
download(link) {
if (rl.settings.app('mobile')) {
if (Settings.app('mobile')) {
open(link, '_self');
focus();
} else {
@ -88,39 +83,27 @@ export class AbstractApp {
}
bootstart() {
const mobile = Settings.app('mobile');
const mobile = Settings.app('mobile'),
register = (key, obj) => ko.components.register(key, obj);
ko.components.register('SaveTrigger', SaveTriggerComponent);
ko.components.register('Input', InputComponent);
ko.components.register('Select', SelectComponent);
ko.components.register('TextArea', TextAreaComponent);
ko.components.register('CheckboxSimple', CheckboxComponent);
if (Settings.app('materialDesign') && !rl.settings.app('mobile')) {
ko.components.register('Checkbox', CheckboxMaterialDesignComponent);
} else {
ko.components.register('Checkbox', CheckboxComponent);
}
register('SaveTrigger', SaveTriggerComponent);
register('Input', InputComponent);
register('Select', SelectComponent);
register('TextArea', TextAreaComponent);
register('CheckboxSimple', CheckboxComponent);
register('Checkbox', Settings.app('materialDesign') && !mobile
? CheckboxMaterialDesignComponent
: CheckboxComponent);
initOnStartOrLangChange();
if (!mobile) {
// mobile
window.addEventListener('resize', () => leftPanelDisabled(767 >= window.innerWidth));
} else {
if (mobile) {
$htmlCL.add('rl-mobile');
leftPanelDisabled(true);
} else {
window.addEventListener('resize', () => leftPanelDisabled(767 >= window.innerWidth));
}
leftPanelDisabled.subscribe((bValue) => {
$htmlCL.toggle('rl-left-panel-disabled', bValue);
$htmlCL.toggle('rl-left-panel-enabled', !bValue);
});
leftPanelType.subscribe((sValue) => {
$htmlCL.toggle('rl-left-panel-none', 'none' === sValue);
$htmlCL.toggle('rl-left-panel-short', 'short' === sValue);
});
leftPanelDisabled.valueHasMutated();
LanguageStore.populate();

View file

@ -17,7 +17,7 @@ import {
ClientSideKeyName
} from 'Common/EnumsUser';
import { $htmlCL, leftPanelDisabled } from 'Common/Globals';
import { doc, $htmlCL, Settings, leftPanelDisabled } from 'Common/Globals';
import { UNUSED_OPTION_VALUE } from 'Common/Consts';
@ -74,9 +74,6 @@ import { FolderSystemPopupView } from 'View/Popup/FolderSystem';
import { AskPopupView } from 'View/Popup/Ask';
import { TwoFactorConfigurationPopupView } from 'View/Popup/TwoFactorConfiguration';
const doc = document,
Settings = rl.settings;
class AppUser extends AbstractApp {
constructor() {
super(Remote);

View file

@ -1,4 +1,5 @@
import * as Links from 'Common/Links';
import { doc } from 'Common/Globals';
let notificator = null,
player = null,
@ -48,7 +49,7 @@ let notificator = null,
console.log('AudioContext ' + audioCtx.state);
audioCtx.resume();
}
unlockEvents.forEach(type => document.removeEventListener(type, unlock, true));
unlockEvents.forEach(type => doc.removeEventListener(type, unlock, true));
// setTimeout(()=>Audio.playNotification(1),1);
};
@ -56,27 +57,21 @@ if (audioCtx) {
audioCtx = audioCtx ? new audioCtx : null;
audioCtx.onstatechange = unlock;
}
unlockEvents.forEach(type => document.addEventListener(type, unlock, true));
unlockEvents.forEach(type => doc.addEventListener(type, unlock, true));
/**
* Browsers can't play without user interaction
*/
const SMAudio = new class {
supported = false;
supportedMp3 = false;
supportedOgg = false;
supportedWav = false;
constructor() {
player || (player = createNewObject());
this.supported = !!player;
this.supportedMp3 = canPlay('audio/mpeg;');
this.supportedWav = canPlay('audio/wav; codecs="1"');
this.supportedOgg = canPlay('audio/ogg; codecs="vorbis"');
if (player) {
this.supportedMp3 = !!canPlay('audio/mpeg;');
this.supportedWav = !!canPlay('audio/wav; codecs="1"');
this.supportedOgg = !!canPlay('audio/ogg; codecs="vorbis"');
const stopFn = () => this.pause();
player.addEventListener('ended', stopFn);
player.addEventListener('error', stopFn);

View file

@ -175,11 +175,11 @@ export const File = {
let result = FileType.Unknown;
const mimeTypeParts = mimeType.split('/'),
type = mimeTypeParts[1],
type = mimeTypeParts[1].replace('x-','').replace('-compressed',''),
match = str => type.includes(str);
switch (true) {
case 'image' === mimeTypeParts[0] || ['png', 'jpg', 'jpeg', 'gif'].includes(ext):
case 'image' === mimeTypeParts[0] || ['png', 'jpg', 'jpeg', 'gif', 'webp'].includes(ext):
result = FileType.Image;
break;
case 'audio' === mimeTypeParts[0] || ['mp3', 'ogg', 'oga', 'wav'].includes(ext):
@ -207,28 +207,18 @@ export const File = {
'rar',
'gzip',
'bzip',
'bzip2',
'x-zip',
'x-7z',
'x-rar',
'x-tar',
'x-gzip',
'x-bzip',
'x-bzip2',
'x-zip-compressed',
'x-7z-compressed',
'x-rar-compressed'
'bzip2'
].includes(type) || ['zip', '7z', 'tar', 'rar', 'gzip', 'bzip', 'bzip2'].includes(ext):
result = FileType.Archive;
break;
case ['pdf', 'x-pdf'].includes(type) || ['pdf'].includes(ext):
case 'pdf' == type || 'pdf' == ext:
result = FileType.Pdf;
break;
case ['application/pgp-signature', 'application/pgp-keys'].includes(mimeType) ||
['asc', 'pem', 'ppk'].includes(ext):
result = FileType.Certificate;
break;
case ['application/pkcs7-signature'].includes(mimeType) || ['p7s'].includes(ext):
case ['application/pkcs7-signature'].includes(mimeType) || 'p7s' == ext:
result = FileType.CertificateBin;
break;
case match(msOffice+'.wordprocessingml') || match(openDoc+'.text') || match('vnd.ms-word')

View file

@ -1,32 +1,47 @@
import ko from 'ko';
import { KeyState } from 'Common/Enums';
export const $html = document.documentElement;
export const $htmlCL = $html.classList;
export const doc = document;
export const $htmlCL = doc.documentElement.classList;
export const Settings = rl.settings;
/**
* @type {?}
*/
export const dropdownVisibility = ko.observable(false).extend({ rateLimit: 0 });
export const moveAction = ko.observable(false);
export const leftPanelDisabled = ko.observable(false);
export const leftPanelType = ko.observable('');
export const leftPanelWidth = ko.observable(0);
leftPanelDisabled.subscribe(value => value && moveAction() && moveAction(false));
leftPanelDisabled.subscribe(value => {
value && moveAction() && moveAction(false);
$htmlCL.toggle('rl-left-panel-disabled', value);
});
leftPanelType.subscribe(sValue => {
$htmlCL.toggle('rl-left-panel-none', 'none' === sValue);
$htmlCL.toggle('rl-left-panel-short', 'short' === sValue);
});
moveAction.subscribe(value => value && leftPanelDisabled() && leftPanelDisabled(false));
// keys
export const keyScopeReal = ko.observable(KeyState.All);
export const keyScopeFake = ko.observable(KeyState.All);
export const keyScope = ko.computed({
read: () => keyScopeFake(),
export const keyScope = (()=>{
let keyScopeFake = KeyState.All;
dropdownVisibility.subscribe(value => {
if (value) {
keyScope(KeyState.Menu);
} else if (KeyState.Menu === shortcuts.getScope()) {
keyScope(keyScopeFake);
}
});
return ko.computed({
read: () => keyScopeFake,
write: value => {
if (KeyState.Menu !== value) {
keyScopeFake(value);
keyScopeFake = value;
if (dropdownVisibility()) {
value = KeyState.Menu;
}
@ -35,13 +50,6 @@ export const keyScope = ko.computed({
keyScopeReal(value);
}
});
})();
keyScopeReal.subscribe(value => shortcuts.setScope(value));
dropdownVisibility.subscribe(value => {
if (value) {
keyScope(KeyState.Menu);
} else if (KeyState.Menu === shortcuts.getScope()) {
keyScope(keyScopeFake());
}
});

View file

@ -1,7 +1,7 @@
import { pString, pInt } from 'Common/Utils';
import { Settings } from 'Common/Globals';
const
Settings = rl.settings,
ROOT = './',
HASH_PREFIX = '#/',
SERVER_PREFIX = './?',
@ -42,25 +42,17 @@ export function rootUser() {
/**
* @param {string} type
* @param {string} download
* @param {string} hash
* @param {string=} customSpecSuffix
* @returns {string}
*/
export function attachmentRaw(type, download, customSpecSuffix) {
customSpecSuffix = undefined === customSpecSuffix ? getHash() : customSpecSuffix;
return (
SERVER_PREFIX +
'/Raw/' +
SUB_QUERY_PREFIX +
'/' +
customSpecSuffix +
'/' +
type +
'/' +
SUB_QUERY_PREFIX +
'/' +
download
);
export function serverRequestRaw(type, hash, customSpecSuffix) {
return SERVER_PREFIX + '/Raw/' + SUB_QUERY_PREFIX + '/'
+ (null == customSpecSuffix ? getHash() : customSpecSuffix) + '/'
+ (type
? type + '/' + (hash ? SUB_QUERY_PREFIX + '/' + hash : '')
: '')
;
}
/**
@ -69,7 +61,7 @@ export function attachmentRaw(type, download, customSpecSuffix) {
* @returns {string}
*/
export function attachmentDownload(download, customSpecSuffix) {
return attachmentRaw('Download', download, customSpecSuffix);
return serverRequestRaw('Download', download, customSpecSuffix);
}
/**
@ -78,7 +70,7 @@ export function attachmentDownload(download, customSpecSuffix) {
* @returns {string}
*/
export function attachmentPreview(download, customSpecSuffix) {
return attachmentRaw('View', download, customSpecSuffix);
return serverRequestRaw('View', download, customSpecSuffix);
}
/**
@ -87,7 +79,7 @@ export function attachmentPreview(download, customSpecSuffix) {
* @returns {string}
*/
export function attachmentThumbnailPreview(download, customSpecSuffix) {
return attachmentRaw('ViewThumbnail', download, customSpecSuffix);
return serverRequestRaw('ViewThumbnail', download, customSpecSuffix);
}
/**
@ -96,7 +88,7 @@ export function attachmentThumbnailPreview(download, customSpecSuffix) {
* @returns {string}
*/
export function attachmentPreviewAsPlain(download, customSpecSuffix) {
return attachmentRaw('ViewAsPlain', download, customSpecSuffix);
return serverRequestRaw('ViewAsPlain', download, customSpecSuffix);
}
/**
@ -105,7 +97,7 @@ export function attachmentPreviewAsPlain(download, customSpecSuffix) {
* @returns {string}
*/
export function attachmentFramed(download, customSpecSuffix) {
return attachmentRaw('FramedView', download, customSpecSuffix);
return serverRequestRaw('FramedView', download, customSpecSuffix);
}
/**
@ -157,17 +149,7 @@ export function change(email) {
* @returns {string}
*/
export function messageViewLink(requestHash) {
return (
SERVER_PREFIX +
'/Raw/' +
SUB_QUERY_PREFIX +
'/' +
getHash() +
'/ViewAsPlain/' +
SUB_QUERY_PREFIX +
'/' +
requestHash
);
return serverRequestRaw('ViewAsPlain', requestHash);
}
/**
@ -175,17 +157,7 @@ export function messageViewLink(requestHash) {
* @returns {string}
*/
export function messageDownloadLink(requestHash) {
return (
SERVER_PREFIX + '/Raw/' + SUB_QUERY_PREFIX + '/' + getHash() + '/Download/' + SUB_QUERY_PREFIX + '/' + requestHash
);
}
/**
* @param {string} email
* @returns {string}
*/
export function avatarLink(email) {
return SERVER_PREFIX + '/Raw/0/Avatar/' + encodeURIComponent(email) + '/';
return serverRequestRaw('Download', requestHash);
}
/**
@ -201,9 +173,7 @@ export function publicLink(hash) {
* @returns {string}
*/
export function userBackground(hash) {
return (
SERVER_PREFIX + '/Raw/' + SUB_QUERY_PREFIX + '/' + getHash() + '/UserBackground/' + SUB_QUERY_PREFIX + '/' + hash
);
return serverRequestRaw('UserBackground', hash);
}
/**
@ -219,14 +189,14 @@ export function langLink(lang, isAdmin) {
* @returns {string}
*/
export function exportContactsVcf() {
return SERVER_PREFIX + '/Raw/' + SUB_QUERY_PREFIX + '/' + getHash() + '/ContactsVcf/';
return serverRequestRaw('ContactsVcf');
}
/**
* @returns {string}
*/
export function exportContactsCsv() {
return SERVER_PREFIX + '/Raw/' + SUB_QUERY_PREFIX + '/' + getHash() + '/ContactsCsv/';
return serverRequestRaw('ContactsCsv');
}
/**
@ -266,13 +236,6 @@ export function openPgpWorkerJs() {
return staticPrefix('js/min/openpgp.worker.min.js');
}
/**
* @returns {string}
*/
export function openPgpWorkerPath() {
return staticPrefix('js/min/');
}
/**
* @param {string} theme
* @returns {string}
@ -303,13 +266,6 @@ export function settings(screenName = '') {
return HASH_PREFIX + 'settings' + (screenName ? '/' + screenName : '');
}
/**
* @returns {string}
*/
export function about() {
return HASH_PREFIX + 'about';
}
/**
* @param {string} screenName
* @returns {string}

View file

@ -1,6 +1,7 @@
import { doc } from 'Common/Globals';
import { i18n } from 'Common/Translator';
export function format(timeStampInUTC, formatStr) {
export function timestampToString(timeStampInUTC, formatStr) {
const now = Date.now(),
time = 0 < timeStampInUTC ? Math.min(now, timeStampInUTC * 1000) : (0 === timeStampInUTC ? now : 0);
@ -36,17 +37,15 @@ export function timeToNode(element, time) {
try {
time = time || (Date.parse(element.dateTime) / 1000);
if (time) {
let key, m = new Date(time * 1000);
element.dateTime = m.format('Y-m-d\\TH:i:s');
element.dateTime = (new Date(time * 1000)).format('Y-m-d\\TH:i:s');
key = element.dataset.momentFormat;
let key = element.dataset.momentFormat;
if (key) {
element.textContent = format(time, key);
element.textContent = timestampToString(time, key);
}
key = element.dataset.momentFormatTitle;
if (key) {
element.title = format(time, key);
if ((key = element.dataset.momentFormatTitle)) {
element.title = timestampToString(time, key);
}
}
} catch (e) {
@ -56,6 +55,6 @@ export function timeToNode(element, time) {
}
addEventListener('reload-time', () => setTimeout(() =>
document.querySelectorAll('[data-bind*="moment:"]').forEach(element => timeToNode(element))
doc.querySelectorAll('[data-bind*="moment:"]').forEach(element => timeToNode(element))
, 1)
);

View file

@ -3,14 +3,6 @@ import { settingsAddViewModel } from 'Screen/AbstractSettings';
const USER_VIEW_MODELS_HOOKS = [],
ADMIN_VIEW_MODELS_HOOKS = [];
/**
* @param {string} name
* @returns {?}
*/
export function mainSettingsGet(name) {
return rl.settings.get(name);
}
/**
* @param {Function} callback
* @param {string} action

View file

@ -1,11 +1,10 @@
import ko from 'ko';
import { Notification, UploadErrorCode } from 'Common/Enums';
import { langLink } from 'Common/Links';
import { doc } from 'Common/Globals';
let I18N_DATA = window.rainloopI18N || {};
const doc = document;
export const trigger = ko.observable(false);
/**
@ -54,8 +53,10 @@ const i18nToNode = element => {
}
}
},
getKeyByValue = (o, v) => Object.keys(o).find(key => o[key] === v);
i18nKey = key => key.replace(/([a-z])([A-Z])/g, '$1_$2').toUpperCase(),
getKeyByValue = (o, v) => Object.keys(o).find(key => o[key] === v);
/**
* @param {Object} elements
@ -80,9 +81,8 @@ export function initOnStartOrLangChange(startCallback, langCallback = null) {
function getNotificationMessage(code) {
let key = getKeyByValue(Notification, code);
if (key) {
key = key.replace('CantCopyMessage', 'CantMoveMessage').replace('UnknownNotification', 'UnknownError');
key = 'NOTIFICATIONS/' + key.replace(/([a-z])([A-Z])/g, '$1_$2').toUpperCase();
return I18N_DATA[key];
key = i18nKey(key).replace('_NOTIFICATION', '_ERROR');
return I18N_DATA['NOTIFICATIONS/' + key];
}
}
@ -129,7 +129,7 @@ export function getUploadErrorDescByCode(code) {
case UploadErrorCode.MissingTempFolder:
case UploadErrorCode.OnSavingFile:
case UploadErrorCode.FileType:
result = getKeyByValue(UploadErrorCode, code).replace(/([a-z])([A-Z])/g, '$1_$2').toUpperCase();
result = i18nKey(getKeyByValue(UploadErrorCode, code));
break;
}
return i18n('UPLOAD/ERROR_' + result);

View file

@ -1,7 +1,9 @@
import { SaveSettingsStep } from 'Common/Enums';
import { doc } from 'Common/Globals';
const
doc = document;
export const
isArray = Array.isArray,
isNonEmptyArray = Array.isNotEmpty;
/**
* @param {*} value

View file

@ -2,10 +2,8 @@ import { ComposeType, FolderType } from 'Common/EnumsUser';
import { EmailModel } from 'Model/Email';
import { showScreenPopup } from 'Knoin/Knoin';
import { encodeHtml } from 'Common/Html';
const
tpl = document.createElement('template'),
isArray = Array.isArray;
import { isArray } from 'Common/Utils';
import { doc } from 'Common/Globals';
/**
* @param {(string|number)} value
@ -81,7 +79,9 @@ export function htmlToPlain(html) {
return '';
};
const convertPre = (...args) =>
const
tpl = doc.createElement('template'),
convertPre = (...args) =>
args && 1 < args.length
? args[1]
.toString()

View file

@ -1,9 +1,9 @@
const config = {
'title': false,
'stylesSet': false,
'customConfig': '',
'contentsCss': '',
'toolbarGroups': [
title: false,
stylesSet: false,
customConfig: '',
contentsCss: '',
toolbarGroups: [
{ name: 'spec' },
{ name: 'styles' },
{ name: 'basicstyles', groups: ['basicstyles', 'cleanup', 'bidi'] },
@ -15,85 +15,56 @@ const config = {
{ name: 'others' }
],
'removePlugins': 'liststyle',
'removeButtons': 'Format,Undo,Redo,Cut,Copy,Paste,Anchor,Strike,Subscript,Superscript,Image,SelectAll,Source',
'removeDialogTabs': 'link:advanced;link:target;image:advanced;images:advanced',
removePlugins: 'liststyle',
removeButtons: 'Format,Undo,Redo,Cut,Copy,Paste,Anchor,Strike,Subscript,Superscript,Image,SelectAll',
removeDialogTabs: 'link:advanced;link:target;image:advanced;images:advanced',
'extraPlugins': 'plain,signature',
extraPlugins: 'plain,signature',
'allowedContent': true,
'extraAllowedContent': true,
allowedContent: true,
extraAllowedContent: true,
'fillEmptyBlocks': false,
'ignoreEmptyParagraph': true,
'disableNativeSpellChecker': false,
fillEmptyBlocks: false,
ignoreEmptyParagraph: true,
disableNativeSpellChecker: false,
'colorButton_enableAutomatic': false,
'colorButton_enableMore': true,
colorButton_enableAutomatic: false,
colorButton_enableMore: true,
'font_defaultLabel': 'Arial',
'fontSize_defaultLabel': '13',
'fontSize_sizes': '10/10px;12/12px;13/13px;14/14px;16/16px;18/18px;20/20px;24/24px;28/28px;36/36px;48/48px'
font_defaultLabel: 'Arial',
fontSize_defaultLabel: '13',
fontSize_sizes: '10/10px;12/12px;13/13px;14/14px;16/16px;18/18px;20/20px;24/24px;28/28px;36/36px;48/48px'
},
/**
* @type {Object}
*/
htmlEditorLangsMap = {
'ar_sa': 'ar-sa',
'bg_bg': 'bg',
'cs_CZ': 'cs',
'de_de': 'de',
'el_gr': 'el',
'es_es': 'es',
'et_ee': 'et',
'fr_fr': 'fr',
'hu_hu': 'hu',
'is_is': 'is',
'it_it': 'it',
'ja_jp': 'ja',
'ko_kr': 'ko',
'lt_lt': 'lt',
'lv_lv': 'lv',
'fa_ir': 'fa',
'nb_no': 'nb',
'nl_nl': 'nl',
'pl_pl': 'pl',
'pt_br': 'pt-br',
'pt_pt': 'pt',
'ro_ro': 'ro',
'ru_ru': 'ru',
'sk_sk': 'sk',
'sl_si': 'sl',
'sv_se': 'sv',
'tr_tr': 'tr',
'uk_ua': 'uk',
'zh_cn': 'zh-cn',
'zh_tw': 'zh'
};
export function createCKEditor(element)
{
const language = rl.settings.get('Language'),
allowSource = !!rl.settings.app('allowHtmlEditorSourceButton'),
biti = !!rl.settings.app('allowHtmlEditorBitiButtons');
const language = (rl.settings.get('Language') || 'en').toLowerCase(),
noSource = !rl.settings.app('allowHtmlEditorSourceButton'),
noBidi = !rl.settings.app('allowHtmlEditorBitiButtons');
if ((allowSource || !biti) && !config.toolbarGroups.__cfgInited) {
config.toolbarGroups.__cfgInited = true;
if (!config.__cfgInited) {
config.__cfgInited = true;
if (allowSource) {
config.removeButtons = config.removeButtons.replace(',Source', '');
if (noSource) {
config.removeButtons += ',Source';
}
if (!biti) {
config.removePlugins += (config.removePlugins ? ',' : '') + 'bidi';
if (noBidi) {
config.removePlugins += ',bidi';
}
}
config.enterMode = CKEDITOR.ENTER_BR;
config.shiftEnterMode = CKEDITOR.ENTER_P;
config.language = htmlEditorLangsMap[(language || 'en').toLowerCase()] || 'en';
config.language = htmlEditorLangsMap[language] || language.substr(0,2);
if (CKEDITOR.env) {
CKEDITOR.env.isCompatible = true;
}
@ -112,13 +83,11 @@ export function createCKEditor(element)
reader = new FileReader();
reader.onloadend = () => {
if (reader.result) {
if ('wysiwyg' === editor.mode) {
if (reader.result && 'wysiwyg' === editor.mode) {
try {
editor.setData(editor.getData().replace(imageId, `<img src="${reader.result}" />`));
} catch (e) {} // eslint-disable-line no-empty
}
}
};
reader.readAsDataURL(file);

View file

@ -3,6 +3,7 @@ import ko from 'ko';
import { HtmlEditor } from 'Common/Html';
import { timeToNode } from 'Common/Momentor';
import { EmailModel } from 'Model/Email';
import { doc } from 'Common/Globals';
const rlContentType = 'snappymail/action',
@ -111,7 +112,7 @@ ko.bindingHandlers.dragmessages = {
if (!rl.settings.app('mobile')) {
element.addEventListener("dragstart", e => {
let data = fValueAccessor()(e);
dragImage || (dragImage = document.getElementById('messagesDragImage'));
dragImage || (dragImage = doc.getElementById('messagesDragImage'));
if (data && dragImage) {
dragImage.querySelector('.text').textContent = data.uids.length;
let img = dragImage.querySelector('.icon-white');

3
dev/External/ko.js vendored
View file

@ -1,8 +1,7 @@
import { i18n, i18nToNodes, trigger } from 'Common/Translator';
import { dropdownVisibility } from 'Common/Globals';
import { doc, dropdownVisibility } from 'Common/Globals';
const
doc = document,
isFunction = v => typeof v === 'function',
koValue = value => !ko.isObservable(value) && isFunction(value) ? value() : ko.unwrap(value);

View file

@ -39,7 +39,9 @@ export class AbstractScreen {
/**
* @returns {void}
*/
__start() {
onStart() {
if (!this.__started) {
this.__started = true;
const routes = this.routes();
if (Array.isNotEmpty(routes)) {
let route = new Crossroads(),
@ -51,3 +53,4 @@ export class AbstractScreen {
}
}
}
}

View file

@ -1,13 +1,13 @@
import ko from 'ko';
import { $htmlCL } from 'Common/Globals';
import { doc, $htmlCL } from 'Common/Globals';
import { isNonEmptyArray } from 'Common/Utils';
let currentScreen = null,
defaultScreenName = '',
popupVisibilityNames = [];
const SCREENS = {},
isNonEmptyArray = Array.isNotEmpty,
autofocus = dom => {
// if (!rl.settings.app('mobile')) {
const af = dom.querySelector('[autofocus]');
@ -54,7 +54,7 @@ export function createCommand(fExecute, fCanExecute = true) {
* @param {string} screenName
* @returns {?Object}
*/
export function screen(screenName) {
function screen(screenName) {
return screenName && null != SCREENS[screenName] ? SCREENS[screenName] : null;
}
@ -78,7 +78,7 @@ function buildViewModel(ViewModelClass, vmScreen) {
let vmDom = null;
const vm = new ViewModelClass(vmScreen),
position = vm.viewModelPosition || '',
vmPlace = position ? document.querySelector('#rl-content #rl-' + position.toLowerCase()) : null;
vmPlace = position ? doc.querySelector('#rl-content #rl-' + position.toLowerCase()) : null;
ViewModelClass.__builded = true;
ViewModelClass.__vm = vm;
@ -223,11 +223,9 @@ function screenOnRoute(screenName, subPart) {
if (!vmScreen.__builded) {
vmScreen.__builded = true;
if (vmScreen.viewModels.length) {
vmScreen.viewModels.forEach(ViewModelClass => {
buildViewModel(ViewModelClass, vmScreen);
});
}
vmScreen.viewModels.forEach(ViewModelClass =>
buildViewModel(ViewModelClass, vmScreen)
);
vmScreen.onBuild && vmScreen.onBuild();
}
@ -301,23 +299,17 @@ export function startScreens(screensClasses) {
const vmScreen = new CScreen(),
screenName = vmScreen && vmScreen.screenName();
if (vmScreen && screenName) {
if (!defaultScreenName) {
defaultScreenName = screenName;
}
if (screenName) {
defaultScreenName || (defaultScreenName = screenName);
SCREENS[screenName] = vmScreen;
}
}
});
Object.values(SCREENS).forEach(vmScreen => {
if (vmScreen && !vmScreen.__started && vmScreen.__start) {
vmScreen.__started = true;
vmScreen.__start();
vmScreen.onStart && vmScreen.onStart();
}
});
Object.values(SCREENS).forEach(vmScreen =>
vmScreen && vmScreen.onStart && vmScreen.onStart()
);
const cross = new Crossroads();
cross.addRoute(/^([a-zA-Z0-9-]*)\/?(.*)$/, screenOnRoute);
@ -326,10 +318,7 @@ export function startScreens(screensClasses) {
hasher.changed.add(cross.parse, cross);
hasher.init();
setTimeout(() => {
$htmlCL.remove('rl-started-trigger');
$htmlCL.add('rl-started');
}, 100);
setTimeout(() => $htmlCL.remove('rl-started-trigger'), 100);
setTimeout(() => $htmlCL.add('rl-started-delay'), 200);
}

View file

@ -4,6 +4,7 @@ import { UNUSED_OPTION_VALUE } from 'Common/Consts';
import { pInt } from 'Common/Utils';
import { ClientSideKeyName, FolderType } from 'Common/EnumsUser';
import * as Cache from 'Common/Cache';
import { Settings } from 'Common/Globals';
import * as Local from 'Storage/Client';
@ -17,8 +18,7 @@ import { i18n, trigger as translatorTrigger } from 'Common/Translator';
import { AbstractModel } from 'Knoin/AbstractModel';
const Settings = rl.settings,
const
ServerFolderType = {
USER: 0,
INBOX: 1,

View file

@ -4,6 +4,7 @@ import { MessagePriority } from 'Common/EnumsUser';
import { i18n } from 'Common/Translator';
import { encodeHtml } from 'Common/Html';
import { isArray } from 'Common/Utils';
import { messageViewLink, messageDownloadLink } from 'Common/Links';
@ -16,8 +17,7 @@ import { AbstractModel } from 'Knoin/AbstractModel';
import PreviewHTML from 'Html/PreviewMessage.html';
const isArray = Array.isArray,
const
SignedVerifyStatus = {
UnknownPublicKeys: -4,
UnknownPrivateKey: -3,

View file

@ -2,6 +2,7 @@ import ko from 'ko';
import { pString } from 'Common/Utils';
import { settings } from 'Common/Links';
import { doc } from 'Common/Globals';
import { AbstractScreen } from 'Knoin/AbstractScreen';
@ -44,7 +45,7 @@ export class AbstractSettingsScreen extends AbstractScreen {
if (RoutedSettingsViewModel.__builded && RoutedSettingsViewModel.__vm) {
settingsScreen = RoutedSettingsViewModel.__vm;
} else {
const vmPlace = document.getElementById('rl-settings-subscreen');
const vmPlace = doc.getElementById('rl-settings-subscreen');
if (vmPlace) {
settingsScreen = new RoutedSettingsViewModel();
@ -101,7 +102,7 @@ export class AbstractSettingsScreen extends AbstractScreen {
);
});
document.querySelector('#rl-content .b-settings .b-content').scrollTop = 0;
doc.querySelector('#rl-content .b-settings .b-content').scrollTop = 0;
}
// --
}, 1);

View file

@ -1,6 +1,6 @@
import { Capa } from 'Common/Enums';
import { Focused, ClientSideKeyName } from 'Common/EnumsUser';
import { leftPanelDisabled, leftPanelType, moveAction } from 'Common/Globals';
import { doc, leftPanelDisabled, leftPanelType, moveAction, Settings } from 'Common/Globals';
import { pString, pInt } from 'Common/Utils';
import { getFolderFromCacheList, getFolderFullNameRaw, getFolderInboxName } from 'Common/Cache';
import { i18n } from 'Common/Translator';
@ -22,8 +22,6 @@ import { AbstractScreen } from 'Knoin/AbstractScreen';
import { ComposePopupView } from 'View/Popup/Compose';
const Settings = rl.settings;
export class MailBoxUserScreen extends AbstractScreen {
constructor() {
super('mailbox', [
@ -38,12 +36,8 @@ export class MailBoxUserScreen extends AbstractScreen {
* @returns {void}
*/
updateWindowTitle() {
let foldersInboxUnreadCount = FolderStore.foldersInboxUnreadCount();
const email = AccountStore.email();
if (Settings.app('listPermanentFiltered')) {
foldersInboxUnreadCount = 0;
}
const foldersInboxUnreadCount = Settings.app('listPermanentFiltered') ? 0 : FolderStore.foldersInboxUnreadCount(),
email = AccountStore.email();
rl.setWindowTitle(
(email
@ -66,10 +60,10 @@ export class MailBoxUserScreen extends AbstractScreen {
leftPanelDisabled(true);
}
if (!Settings.capa(Capa.Folders)) {
leftPanelType(Settings.capa(Capa.Composer) || Settings.capa(Capa.Contacts) ? 'short' : 'none');
} else {
if (Settings.capa(Capa.Folders)) {
leftPanelType('');
} else {
leftPanelType(Settings.capa(Capa.Composer) || Settings.capa(Capa.Contacts) ? 'short' : 'none');
}
}
@ -80,10 +74,9 @@ export class MailBoxUserScreen extends AbstractScreen {
* @returns {void}
*/
onRoute(folderHash, page, search) {
let threadUid = folderHash.replace(/^(.+)~([\d]+)$/, '$2');
const folder = getFolderFromCacheList(getFolderFullNameRaw(folderHash.replace(/~([\d]+)$/, '')));
if (folder) {
let threadUid = folderHash.replace(/^(.+)~([\d]+)$/, '$2');
if (folderHash === threadUid) {
threadUid = '';
}
@ -102,6 +95,8 @@ export class MailBoxUserScreen extends AbstractScreen {
* @returns {void}
*/
onStart() {
if (!this.__started) {
super.onStart();
setTimeout(() => SettingsStore.layout.valueHasMutated(), 50);
setTimeout(() => warmUpScreenPopup(ComposePopupView), 500);
@ -109,15 +104,14 @@ export class MailBoxUserScreen extends AbstractScreen {
FolderStore.foldersInboxUnreadCount(e.detail);
const email = AccountStore.email();
AccountStore.accounts.forEach(item => {
if (item && email === item.email) {
item.count(e.detail);
}
});
AccountStore.accounts.forEach(item =>
item && email === item.email && item.count(e.detail)
);
this.updateWindowTitle();
});
}
}
/**
* @returns {void}
@ -129,7 +123,7 @@ export class MailBoxUserScreen extends AbstractScreen {
, 1);
}
document.addEventListener('click', event =>
doc.addEventListener('click', event =>
event.target.closest('#rl-right') && moveAction(false)
);
}
@ -138,30 +132,19 @@ export class MailBoxUserScreen extends AbstractScreen {
* @returns {Array}
*/
routes() {
const inboxFolderName = getFolderInboxName(),
const
fNormS = (request, vals) => {
if (request) {
vals[0] = pString(vals[0]);
vals[1] = pInt(vals[1]);
vals[1] = 0 >= vals[1] ? 1 : vals[1];
vals[2] = pString(vals[2]);
if (!request) {
vals[0] = inboxFolderName;
} else {
vals[0] = getFolderInboxName();
vals[1] = 1;
}
return [decodeURI(vals[0]), vals[1], decodeURI(vals[2])];
return [decodeURI(vals[0]), 1 > vals[1] ? 1 : vals[1], decodeURI(pString(vals[2]))];
},
fNormD = (request, vals) => {
vals[0] = pString(vals[0]);
vals[1] = pString(vals[1]);
if (!request) {
vals[0] = inboxFolderName;
}
return [decodeURI(vals[0]), 1, decodeURI(vals[1])];
};
fNormD = (request, vals) =>
[decodeURI(request ? pString(vals[0]) : getFolderInboxName()), 1, decodeURI(pString(vals[1]))];
return [
[/^([a-zA-Z0-9~]+)\/p([1-9][0-9]*)\/(.+)\/?$/, { 'normalize_': fNormS }],

View file

@ -1,5 +1,5 @@
import { Capa, KeyState } from 'Common/Enums';
import { keyScope, leftPanelType, leftPanelDisabled } from 'Common/Globals';
import { keyScope, leftPanelType, leftPanelDisabled, Settings } from 'Common/Globals';
import { runSettingsViewModelHooks } from 'Common/Plugins';
import { initOnStartOrLangChange, i18n } from 'Common/Translator';
@ -22,8 +22,6 @@ import { SystemDropDownSettingsUserView } from 'View/User/Settings/SystemDropDow
import { MenuSettingsUserView } from 'View/User/Settings/Menu';
import { PaneSettingsUserView } from 'View/User/Settings/Pane';
const Settings = rl.settings;
export class SettingsUserScreen extends AbstractSettingsScreen {
constructor() {
super([SystemDropDownSettingsUserView, MenuSettingsUserView, PaneSettingsUserView]);

View file

@ -14,7 +14,7 @@ import { showScreenPopup } from 'Knoin/Knoin';
import Remote from 'Remote/Admin/Fetch';
import ThemeStore from 'Stores/Theme';
import { ThemeStore } from 'Stores/Theme';
import LanguageStore from 'Stores/Language';
import AppAdminStore from 'Stores/Admin/App';
import CapaAdminStore from 'Stores/Admin/Capa';

View file

@ -4,8 +4,9 @@ import { SaveSettingsStep, UploadErrorCode, Capa } from 'Common/Enums';
import { changeTheme, convertThemeName } from 'Common/Utils';
import { userBackground, themePreviewLink, uploadBackground } from 'Common/Links';
import { i18n } from 'Common/Translator';
import { doc, $htmlCL } from 'Common/Globals';
import ThemeStore from 'Stores/Theme';
import { ThemeStore } from 'Stores/Theme';
import Remote from 'Remote/User/Fetch';
@ -39,13 +40,12 @@ export class ThemesUserSettings {
});
this.background.hash.subscribe((value) => {
const b = document.body, cl = document.documentElement.classList;
if (!value) {
cl.remove('UserBackground');
b.removeAttribute('style');
$htmlCL.remove('UserBackground');
doc.body.removeAttribute('style');
} else {
cl.add('UserBackground');
b.style.backgroundImage = "url("+userBackground(value)+")";
$htmlCL.add('UserBackground');
doc.body.style.backgroundImage = "url("+userBackground(value)+")";
}
});
}

View file

@ -1,15 +1,11 @@
import ko from 'ko';
class ThemeStore {
constructor() {
this.themes = ko.observableArray();
this.themeBackgroundName = ko.observable('');
this.themeBackgroundHash = ko.observable('');
export const ThemeStore = {
themes: ko.observableArray(),
themeBackgroundName: ko.observable(''),
themeBackgroundHash: ko.observable(''),
this.theme = ko.observable('').extend({ limitedList: this.themes });
}
populate() {
populate: function(){
const Settings = rl.settings,
themes = Settings.app('themes');
@ -18,6 +14,6 @@ class ThemeStore {
this.themeBackgroundName(Settings.get('UserBackgroundName'));
this.themeBackgroundHash(Settings.get('UserBackgroundHash'));
}
}
};
export default new ThemeStore();
ThemeStore.theme = ko.observable('').extend({ limitedList: ThemeStore.themes });

View file

@ -2,9 +2,7 @@ import ko from 'ko';
import { KeyState } from 'Common/Enums';
import { Focused } from 'Common/EnumsUser';
import { keyScope, leftPanelDisabled } from 'Common/Globals';
const Settings = rl.settings;
import { keyScope, leftPanelDisabled, Settings } from 'Common/Globals';
class AppUserStore {
constructor() {

View file

@ -2,7 +2,7 @@ import ko from 'ko';
import { StorageResultType, Notification } from 'Common/Enums';
import { Layout, Focused, MessageSetAction } from 'Common/EnumsUser';
import { doc } from 'Common/Globals';
import { pInt, pString } from 'Common/Utils';
import { plainToHtml } from 'Common/UtilsUser';
@ -52,7 +52,7 @@ const
let iMessageBodyCacheCount = 0;
document.body.append(hcont);
doc.body.append(hcont);
class MessageUserStore {
constructor() {
@ -485,7 +485,7 @@ class MessageUserStore {
if (messagesDom) {
id = 'rl-mgs-' + message.hash.replace(/[^a-zA-Z0-9]/g, '');
const textBody = document.getElementById(id);
const textBody = doc.getElementById(id);
if (textBody) {
textBody.rlCacheCount = ++iMessageBodyCacheCount;
message.body = textBody;
@ -508,7 +508,7 @@ class MessageUserStore {
/-----BEGIN PGP SIGNED MESSAGE-----/.test(plain) && /-----BEGIN PGP SIGNATURE-----/.test(plain);
}
const pre = document.createElement('pre');
const pre = doc.createElement('pre');
if (pgpSigned && message.isPgpSigned()) {
pre.className = 'b-plain-openpgp signed';
pre.textContent = plain;

View file

@ -2,6 +2,7 @@ import ko from 'ko';
import { i18n } from 'Common/Translator';
import { pString } from 'Common/Utils';
import { doc } from 'Common/Globals';
import AccountStore from 'Stores/User/Account';
@ -360,7 +361,7 @@ class PgpUserStore {
verControl.addEventHandler('click', domControlSignedClickHelper(this, dom, domText));
}
dom.before(verControl, document.createElement('div'));
dom.before(verControl, doc.createElement('div'));
}
}
}

View file

@ -3,6 +3,7 @@ import ko from 'ko';
import { MESSAGES_PER_PAGE_VALUES } from 'Common/Consts';
import { Layout, EditorDefaultType } from 'Common/EnumsUser';
import { pInt } from 'Common/Utils';
import { doc } from 'Common/Globals';
class SettingsUserStore {
constructor() {
@ -39,7 +40,7 @@ class SettingsUserStore {
}
subscribers() {
const htmlCL = document.documentElement.classList;
const htmlCL = doc.documentElement.classList;
this.layout.subscribe(value => {
htmlCL.toggle('rl-no-preview-pane', Layout.NoPreview === value);
htmlCL.toggle('rl-side-preview-pane', Layout.SidePreview === value);

View file

@ -24,7 +24,7 @@ html.rl-mobile {
min-height: 250px;
}
&.rl-left-panel-enabled #rl-right {
&:not(.rl-left-panel-disabled) #rl-right {
right: -150px;
}

View file

@ -14,17 +14,16 @@ import {
SetSystemFoldersNotification
} from 'Common/EnumsUser';
import { inFocus, pInt } from 'Common/Utils';
import { inFocus, pInt, isArray, isNonEmptyArray } from 'Common/Utils';
import { delegateRunOnDestroy } from 'Common/UtilsUser';
import { encodeHtml } from 'Common/Html';
import { encodeHtml, HtmlEditor } from 'Common/Html';
import { UNUSED_OPTION_VALUE } from 'Common/Consts';
import { upload } from 'Common/Links';
import { i18n, getNotification, getUploadErrorDescByCode } from 'Common/Translator';
import { format as momentorFormat } from 'Common/Momentor';
import { timestampToString } from 'Common/Momentor';
import { MessageFlagsCache, setFolderHash } from 'Common/Cache';
import { HtmlEditor } from 'Common/Html';
import { Settings } from 'Common/Globals';
import AppStore from 'Stores/User/App';
import SettingsStore from 'Stores/User/Settings';
@ -46,7 +45,7 @@ import { AskPopupView } from 'View/Popup/Ask';
import { ContactsPopupView } from 'View/Popup/Contacts';
import { ComposeOpenPgpPopupView } from 'View/Popup/ComposeOpenPgp';
const Settings = rl.settings,
const
/**
* @param {string} prefix
* @param {string} subject
@ -324,7 +323,7 @@ class ComposePopupView extends AbstractViewPopup {
},
attachmentsInProcess: value => {
if (this.attachmentsInProcessError() && Array.isNotEmpty(value)) {
if (this.attachmentsInProcessError() && isNonEmptyArray(value)) {
this.attachmentsInProcessError(false);
}
}
@ -395,7 +394,7 @@ class ComposePopupView extends AbstractViewPopup {
if (!this.emptyToError() && !this.attachmentsInErrorError() && !this.attachmentsInProcessError()) {
if (SettingsStore.replySameFolder()) {
if (
Array.isArray(this.aDraftInfo) &&
isArray(this.aDraftInfo) &&
3 === this.aDraftInfo.length &&
null != this.aDraftInfo[2] &&
this.aDraftInfo[2].length
@ -414,7 +413,7 @@ class ComposePopupView extends AbstractViewPopup {
this.sendError(false);
this.sending(true);
if (Array.isArray(this.aDraftInfo) && 3 === this.aDraftInfo.length) {
if (isArray(this.aDraftInfo) && 3 === this.aDraftInfo.length) {
const flagsCache = MessageFlagsCache.getFor(this.aDraftInfo[2], this.aDraftInfo[1]);
if (flagsCache) {
if ('forward' === this.aDraftInfo[0]) {
@ -820,7 +819,7 @@ class ComposePopupView extends AbstractViewPopup {
* @param {Array} emails
*/
addEmailsTo(fKoValue, emails) {
if (Array.isNotEmpty(emails)) {
if (isNonEmptyArray(emails)) {
const value = fKoValue().trim(),
values = emails.map(item => item ? item.toLine(false) : null)
.validUnique();
@ -870,9 +869,9 @@ class ComposePopupView extends AbstractViewPopup {
oMessageOrArray = oMessageOrArray || null;
if (oMessageOrArray) {
message =
Array.isArray(oMessageOrArray) && 1 === oMessageOrArray.length
isArray(oMessageOrArray) && 1 === oMessageOrArray.length
? oMessageOrArray[0]
: !Array.isArray(oMessageOrArray)
: !isArray(oMessageOrArray)
? oMessageOrArray
: null;
}
@ -890,20 +889,20 @@ class ComposePopupView extends AbstractViewPopup {
excludeEmail[identity.email()] = true;
}
if (Array.isNotEmpty(aToEmails)) {
if (isNonEmptyArray(aToEmails)) {
this.to(this.emailArrayToStringLineHelper(aToEmails));
}
if (Array.isNotEmpty(aCcEmails)) {
if (isNonEmptyArray(aCcEmails)) {
this.cc(this.emailArrayToStringLineHelper(aCcEmails));
}
if (Array.isNotEmpty(aBccEmails)) {
if (isNonEmptyArray(aBccEmails)) {
this.bcc(this.emailArrayToStringLineHelper(aBccEmails));
}
if (lineComposeType && message) {
sDate = momentorFormat(message.dateTimeStampInUTC(), 'FULL');
sDate = timestampToString(message.dateTimeStampInUTC(), 'FULL');
sSubject = message.subject();
aDraftInfo = message.aDraftInfo;
sText = message.bodyAsHTML();
@ -963,7 +962,7 @@ class ComposePopupView extends AbstractViewPopup {
this.subject(sSubject);
this.prepareMessageAttachments(message, lineComposeType);
this.aDraftInfo = Array.isNotEmpty(aDraftInfo) && 3 === aDraftInfo.length ? aDraftInfo : null;
this.aDraftInfo = isNonEmptyArray(aDraftInfo) && 3 === aDraftInfo.length ? aDraftInfo : null;
this.sInReplyTo = message.sInReplyTo;
this.sReferences = message.sReferences;
break;
@ -977,7 +976,7 @@ class ComposePopupView extends AbstractViewPopup {
this.subject(sSubject);
this.prepareMessageAttachments(message, lineComposeType);
this.aDraftInfo = Array.isNotEmpty(aDraftInfo) && 3 === aDraftInfo.length ? aDraftInfo : null;
this.aDraftInfo = isNonEmptyArray(aDraftInfo) && 3 === aDraftInfo.length ? aDraftInfo : null;
this.sInReplyTo = message.sInReplyTo;
this.sReferences = message.sReferences;
break;
@ -1070,7 +1069,7 @@ class ComposePopupView extends AbstractViewPopup {
this.setFocusInPopup();
});
} else if (Array.isNotEmpty(oMessageOrArray)) {
} else if (isNonEmptyArray(oMessageOrArray)) {
oMessageOrArray.forEach(item => {
this.addMessageAsAttachment(item);
});
@ -1096,7 +1095,7 @@ class ComposePopupView extends AbstractViewPopup {
}
const downloads = this.getAttachmentsDownloadsForUpload();
if (Array.isNotEmpty(downloads)) {
if (isNonEmptyArray(downloads)) {
Remote.messageUploadAttachments((sResult, oData) => {
if (StorageResultType.Success === sResult && oData && oData.Result) {
Object.entries(oData.Result).forEach(([tempName, id]) => {

View file

@ -1,5 +1,5 @@
import { KeyState } from 'Common/Enums';
import { doc } from 'Common/Globals';
import { AbstractViewPopup } from 'Knoin/AbstractViews';
class ViewOpenPgpKeyPopupView extends AbstractViewPopup {
@ -22,7 +22,7 @@ class ViewOpenPgpKeyPopupView extends AbstractViewPopup {
const el = this.keyDom();
if (el) {
let sel = getSelection(),
range = document.createRange();
range = doc.createRange();
sel.removeAllRanges();
range.selectNodeContents(el);
sel.addRange(range);

View file

@ -11,7 +11,7 @@ import { AbstractViewRight } from 'Knoin/AbstractViews';
import { KeyboardShortcutsHelpPopupView } from 'View/Popup/KeyboardShortcutsHelp';
import { AccountPopupView } from 'View/Popup/Account';
const Settings = rl.settings;
import { Settings } from 'Common/Globals';
export class AbstractSystemDropDownUserView extends AbstractViewRight {
constructor(name) {

View file

@ -19,12 +19,12 @@ import Remote from 'Remote/User/Fetch';
import { command, showScreenPopup } from 'Knoin/Knoin';
import { AbstractViewCenter } from 'Knoin/AbstractViews';
import { Settings } from 'Common/Globals';
import { rootAdmin } from 'Common/Links';
import { LanguagesPopupView } from 'View/Popup/Languages';
const Settings = rl.settings,
const
LoginSignMeType = {
DefaultOff: 0,
DefaultOn: 1,

View file

@ -2,7 +2,7 @@ import ko from 'ko';
import { Capa, KeyState } from 'Common/Enums';
import { Focused, Layout } from 'Common/EnumsUser';
import { leftPanelDisabled, moveAction } from 'Common/Globals';
import { leftPanelDisabled, moveAction, Settings } from 'Common/Globals';
import { mailBox, settings } from 'Common/Links';
import { setFolderHash } from 'Common/Cache';
@ -18,8 +18,6 @@ import { ComposePopupView } from 'View/Popup/Compose';
import { FolderCreatePopupView } from 'View/Popup/FolderCreate';
import { ContactsPopupView } from 'View/Popup/Contacts';
const Settings = rl.settings;
class FolderListMailBoxUserView extends AbstractViewLeft {
constructor() {
super('User/MailBox/FolderList', 'MailFolderList');

View file

@ -16,7 +16,7 @@ import {
import { UNUSED_OPTION_VALUE } from 'Common/Consts';
import { leftPanelDisabled, moveAction } from 'Common/Globals';
import { doc, leftPanelDisabled, moveAction, Settings } from 'Common/Globals';
import { computedPaginatorHelper } from 'Common/UtilsUser';
import { File } from 'Common/File';
@ -49,7 +49,6 @@ import { ComposePopupView } from 'View/Popup/Compose';
import { AdvancedSearchPopupView } from 'View/Popup/AdvancedSearch';
const
Settings = rl.settings,
canBeMovedHelper = (self) => self.canBeMoved(),
ifvisible = window.ifvisible;
@ -456,7 +455,7 @@ class MessageListMailBoxUserView extends AbstractViewRight {
}
getDragData(event) {
const item = ko.dataFor(document.elementFromPoint(event.clientX, event.clientY));
const item = ko.dataFor(doc.elementFromPoint(event.clientX, event.clientY));
item && item.checked && item.checked(true);
const uids = MessageStore.messageListCheckedOrSelectedUidsWithSubMails();
item && !uids.includes(item.uid) && uids.push(item.uid);

View file

@ -16,7 +16,7 @@ import {
MessageSetAction
} from 'Common/EnumsUser';
import { $htmlCL, leftPanelDisabled, keyScopeReal, moveAction } from 'Common/Globals';
import { $htmlCL, leftPanelDisabled, keyScopeReal, moveAction, Settings } from 'Common/Globals';
import { inFocus } from 'Common/Utils';
import { mailToHelper } from 'Common/UtilsUser';
@ -43,8 +43,6 @@ import { AbstractViewRight } from 'Knoin/AbstractViews';
import { ComposePopupView } from 'View/Popup/Compose';
const Settings = rl.settings;
function isTransparent(color) {
return 'rgba(0, 0, 0, 0)' === color || 'transparent' === color;
}

6
dev/bootstrap.js vendored
View file

@ -1,4 +1,4 @@
import { dropdownVisibility } from 'Common/Globals';
import { doc, dropdownVisibility } from 'Common/Globals';
import * as Enums from 'Common/Enums';
import * as Plugins from 'Common/Plugins';
import { i18n } from 'Common/Translator';
@ -38,7 +38,6 @@ export default (App) => {
rl.addSettingsViewModel = Plugins.addSettingsViewModel;
rl.addSettingsViewModelForAdmin = Plugins.addSettingsViewModelForAdmin;
rl.settingsGet = Plugins.mainSettingsGet;
rl.pluginSettingsGet = Plugins.settingsGet;
rl.pluginRemoteRequest = Plugins.remoteRequest;
@ -140,8 +139,7 @@ export default (App) => {
};
window.__APP_BOOT = fErrorCallback => {
const doc = document,
cb = () => setTimeout(() => {
const cb = () => setTimeout(() => {
if (rl.TEMPLATES) {
doc.getElementById('rl-templates').innerHTML = rl.TEMPLATES;
setTimeout(() => App.bootstart(), 10);

View file

@ -1,18 +1,12 @@
$(function () {
if (window.snowFall && window.rl && !window.rl.settingsGet('Auth'))
if (!/iphone|ipod|ipad|android/i.test(navigator.userAgent))
{
var
sUserAgent = (navigator.userAgent || '').toLowerCase(),
bIsiOSDevice = -1 < sUserAgent.indexOf('iphone') || -1 < sUserAgent.indexOf('ipod') || -1 < sUserAgent.indexOf('ipad'),
bIsAndroidDevice = -1 < sUserAgent.indexOf('android')
;
if (!bIsiOSDevice && !bIsAndroidDevice)
document.addEventListener('DOMContentLoaded', () => {
if (window.snowFall && window.rl && !rl.settings.get('Auth'))
{
window.snowFall.snow(document.getElementsByTagName('body'), {
shadow: true, round: true, minSize: 2, maxSize: 5
});
}
}
});
}

View file

@ -179,6 +179,7 @@ en:
CANT_GET_MESSAGE_LIST: "Can't get message list"
CANT_GET_MESSAGE: "Can't get message"
CANT_DELETE_MESSAGE: "Can't delete message"
CANT_COPY_MESSAGE: "Can't copy message"
CANT_MOVE_MESSAGE: "Can't move message"
CANT_SAVE_MESSAGE: "Can't save message"
CANT_SEND_MESSAGE: "Can't send message"

View file

@ -175,6 +175,7 @@ de_DE:
CANT_GET_MESSAGE_LIST: "Die Nachrichtenliste ist nicht verfügbar"
CANT_GET_MESSAGE: "Diese Nachricht ist nicht verfügbar"
CANT_DELETE_MESSAGE: "Diese Nachricht kann nicht gelöscht werden"
CANT_COPY_MESSAGE: "Diese Nachricht kann nicht kopiert werden"
CANT_MOVE_MESSAGE: "Diese Nachricht kann nicht verschoben werden"
CANT_SAVE_MESSAGE: "Diese Nachricht kann nicht gespeichert werden"
CANT_SEND_MESSAGE: "Diese Nachricht kann nicht gesendet werden"

View file

@ -176,6 +176,7 @@ en_US:
CANT_GET_MESSAGE_LIST: "Can't get message list"
CANT_GET_MESSAGE: "Can't get message"
CANT_DELETE_MESSAGE: "Can't delete message"
CANT_COPY_MESSAGE: "Can't copy message"
CANT_MOVE_MESSAGE: "Can't move message"
CANT_SAVE_MESSAGE: "Can't save message"
CANT_SEND_MESSAGE: "Can't send message"

View file

@ -176,6 +176,7 @@ es_ES:
CANT_GET_MESSAGE_LIST: "No se puede obtener la lista de mensajes"
CANT_GET_MESSAGE: "No se puede obtener el mensaje"
CANT_DELETE_MESSAGE: "No se puede eliminar el mensaje"
CANT_COPY_MESSAGE: "No se puede copiar el mensaje"
CANT_MOVE_MESSAGE: "No se puede mover el mensaje"
CANT_SAVE_MESSAGE: "No se puede guardar el mensaje"
CANT_SEND_MESSAGE: "No se puede enviar el mensaje"

View file

@ -176,6 +176,7 @@ fr_FR:
CANT_GET_MESSAGE_LIST: "Impossible d'obtenir la liste des messages"
CANT_GET_MESSAGE: "Impossible d'obtenir le message"
CANT_DELETE_MESSAGE: "Impossible de supprimer le message"
CANT_COPY_MESSAGE: "Impossible de copier le message"
CANT_MOVE_MESSAGE: "Impossible de déplacer le message"
CANT_SAVE_MESSAGE: "Impossible d'enregistrer le message"
CANT_SEND_MESSAGE: "Impossible d'envoyer le message"

View file

@ -175,6 +175,7 @@ nl_NL:
CANT_GET_MESSAGE_LIST: "Kan berichtenlijst niet ophalen"
CANT_GET_MESSAGE: "Kan bericht niet ophalen"
CANT_DELETE_MESSAGE: "Kan bericht niet verwijderen"
CANT_COPY_MESSAGE: "Kan bericht niet kopiëren"
CANT_MOVE_MESSAGE: "Kan bericht niet verplaatsen"
CANT_SAVE_MESSAGE: "Kan bericht niet opslaan"
CANT_SEND_MESSAGE: "Kan bericht niet verzenden"

View file

@ -176,6 +176,7 @@ zh_CN:
CANT_GET_MESSAGE_LIST: "无法获取邮件列表"
CANT_GET_MESSAGE: "无法获取邮件"
CANT_DELETE_MESSAGE: "无法删除邮件"
CANT_COPY_MESSAGE: "无法复制邮件"
CANT_MOVE_MESSAGE: "无法移动邮件"
CANT_SAVE_MESSAGE: "无法保存邮件"
CANT_SEND_MESSAGE: "无法发送邮件"

View file

@ -523,6 +523,7 @@ en:
CANT_GET_MESSAGE_LIST: "Can't get message list"
CANT_GET_MESSAGE: "Can't get message"
CANT_DELETE_MESSAGE: "Can't delete message"
CANT_COPY_MESSAGE: "Can't copy message"
CANT_MOVE_MESSAGE: "Can't move message"
CANT_SAVE_MESSAGE: "Can't save message"
CANT_SEND_MESSAGE: "Can't send message"

View file

@ -524,6 +524,7 @@ de_DE:
CANT_GET_MESSAGE_LIST: "Die Nachrichtenliste ist nicht verfügbar"
CANT_GET_MESSAGE: "Diese Nachricht ist nicht verfügbar"
CANT_DELETE_MESSAGE: "Diese Nachricht kann nicht gelöscht werden"
CANT_COPY_MESSAGE: "Diese Nachricht kann nicht kopiert werden"
CANT_MOVE_MESSAGE: "Diese Nachricht kann nicht verschoben werden"
CANT_SAVE_MESSAGE: "Diese Nachricht kann nicht gespeichert werden"
CANT_SEND_MESSAGE: "Diese Nachricht kann nicht gesendet werden"

View file

@ -523,6 +523,7 @@ en_GB:
CANT_GET_MESSAGE_LIST: "Can't get message list"
CANT_GET_MESSAGE: "Can't get message"
CANT_DELETE_MESSAGE: "Can't delete message"
CANT_COPY_MESSAGE: "Can't copy message"
CANT_MOVE_MESSAGE: "Can't move message"
CANT_SAVE_MESSAGE: "Can't save message"
CANT_SEND_MESSAGE: "Can't send message"

View file

@ -523,6 +523,7 @@ en_US:
CANT_GET_MESSAGE_LIST: "Can't get message list"
CANT_GET_MESSAGE: "Can't get message"
CANT_DELETE_MESSAGE: "Can't delete message"
CANT_COPY_MESSAGE: "Can't copy message"
CANT_MOVE_MESSAGE: "Can't move message"
CANT_SAVE_MESSAGE: "Can't save message"
CANT_SEND_MESSAGE: "Can't send message"

View file

@ -525,6 +525,7 @@ es_ES:
CANT_GET_MESSAGE_LIST: "No se puede obtener la lista de mensajes"
CANT_GET_MESSAGE: "No se puede obtener el mensaje"
CANT_DELETE_MESSAGE: "No se puede eliminar el mensaje"
CANT_COPY_MESSAGE: "No se puede copiar el mensaje"
CANT_MOVE_MESSAGE: "No se puede mover el mensaje"
CANT_SAVE_MESSAGE: "No se puede guardar el mensaje"
CANT_SEND_MESSAGE: "No se puede enviar el mensaje"

View file

@ -524,6 +524,7 @@ fr_FR:
CANT_GET_MESSAGE_LIST: "Impossible d'obtenir la liste des messages"
CANT_GET_MESSAGE: "Impossible d'obtenir le message"
CANT_DELETE_MESSAGE: "Impossible de supprimer le message"
CANT_COPY_MESSAGE: "Impossible de copier le message"
CANT_MOVE_MESSAGE: "Impossible de déplacer le message"
CANT_SAVE_MESSAGE: "Impossible d'enregistrer le message"
CANT_SEND_MESSAGE: "Impossible d'envoyer le message"

View file

@ -523,6 +523,7 @@ nl_NL:
CANT_GET_MESSAGE_LIST: "Berichtenlijst kan niet worden opgehaald"
CANT_GET_MESSAGE: "Bericht kan niet worden opgehaald"
CANT_DELETE_MESSAGE: "Kan bericht niet verwijderen"
CANT_COPY_MESSAGE: "Kan bericht niet kopiëren"
CANT_MOVE_MESSAGE: "Kan bericht niet verplaatsen"
CANT_SAVE_MESSAGE: "Kan bericht niet opslaan"
CANT_SEND_MESSAGE: "Kan bericht niet verzenden"

View file

@ -521,6 +521,7 @@ zh_CN:
CANT_GET_MESSAGE_LIST: "无法获取邮件列表"
CANT_GET_MESSAGE: "无法获取邮件"
CANT_DELETE_MESSAGE: "无法删除邮件"
CANT_COPY_MESSAGE: "无法复制邮件"
CANT_MOVE_MESSAGE: "无法移动邮件"
CANT_SAVE_MESSAGE: "无法保存邮件"
CANT_SEND_MESSAGE: "无法发送邮件"