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 | |js/* |RainLoop |Snappy |
|--------------- |--------: |--------: | |--------------- |--------: |--------: |
|admin.js |2.130.942 | 123.042 | |admin.js |2.130.942 | 120.785 |
|app.js |4.184.455 | 534.334 | |app.js |4.184.455 | 529.074 |
|boot.js | 671.522 | 4.842 | |boot.js | 671.522 | 4.842 |
|libs.js | 647.614 | 235.475 | |libs.js | 647.614 | 235.475 |
|polyfills.js | 325.834 | 0 | |polyfills.js | 325.834 | 0 |
|serviceworker.js | 0 | 285 | |serviceworker.js | 0 | 285 |
|TOTAL |7.960.367 | 897.978 | |TOTAL |7.960.367 | 890.449 |
|js/min/* |RainLoop |Snappy |Rain gzip |gzip |brotli | |js/min/* |RainLoop |Snappy |Rain gzip |gzip |brotli |
|--------------- |--------: |--------: |--------: |--------: |--------: | |--------------- |--------: |--------: |--------: |--------: |--------: |
|admin.min.js | 252.147 | 63.913 | 73.657 | 18.158 | 16.135 | |admin.min.js | 252.147 | 62.863 | 73.657 | 18.009 | 15.992 |
|app.min.js | 511.202 | 262.917 |140.462 | 74.870 | 62.686 | |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 | |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 | |libs.min.js | 572.545 | 130.930 |176.720 | 47.397 | 42.116 |
|polyfills.min.js | 32.452 | 0 | 11.312 | 0 | 0 | |polyfills.min.js | 32.452 | 0 | 11.312 | 0 | 0 |
|TOTAL |1.434.353 | 460.390 |424.718 |141.800 |122.126 | |TOTAL |1.434.353 | 455.957 |424.718 |140.786 |121.481 |
|TOTAL (no admin) |1.182.206 | 396.477 |351.061 |123.642 |105.991 | |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 ### CSS changes

View file

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

View file

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

View file

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

View file

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

View file

@ -1,47 +1,55 @@
import ko from 'ko'; import ko from 'ko';
import { KeyState } from 'Common/Enums'; import { KeyState } from 'Common/Enums';
export const $html = document.documentElement; export const doc = document;
export const $htmlCL = $html.classList;
export const $htmlCL = doc.documentElement.classList;
export const Settings = rl.settings;
/**
* @type {?}
*/
export const dropdownVisibility = ko.observable(false).extend({ rateLimit: 0 }); export const dropdownVisibility = ko.observable(false).extend({ rateLimit: 0 });
export const moveAction = ko.observable(false); export const moveAction = ko.observable(false);
export const leftPanelDisabled = ko.observable(false); export const leftPanelDisabled = ko.observable(false);
export const leftPanelType = ko.observable(''); 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)); moveAction.subscribe(value => value && leftPanelDisabled() && leftPanelDisabled(false));
// keys // keys
export const keyScopeReal = ko.observable(KeyState.All); export const keyScopeReal = ko.observable(KeyState.All);
export const keyScopeFake = ko.observable(KeyState.All);
export const keyScope = ko.computed({ export const keyScope = (()=>{
read: () => keyScopeFake(), let keyScopeFake = KeyState.All;
write: value => { dropdownVisibility.subscribe(value => {
if (KeyState.Menu !== value) { if (value) {
keyScopeFake(value); keyScope(KeyState.Menu);
if (dropdownVisibility()) { } else if (KeyState.Menu === shortcuts.getScope()) {
value = KeyState.Menu; keyScope(keyScopeFake);
}
} }
});
return ko.computed({
read: () => keyScopeFake,
write: value => {
if (KeyState.Menu !== value) {
keyScopeFake = value;
if (dropdownVisibility()) {
value = KeyState.Menu;
}
}
keyScopeReal(value); keyScopeReal(value);
} }
}); });
})();
keyScopeReal.subscribe(value => shortcuts.setScope(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 { pString, pInt } from 'Common/Utils';
import { Settings } from 'Common/Globals';
const const
Settings = rl.settings,
ROOT = './', ROOT = './',
HASH_PREFIX = '#/', HASH_PREFIX = '#/',
SERVER_PREFIX = './?', SERVER_PREFIX = './?',
@ -42,25 +42,17 @@ export function rootUser() {
/** /**
* @param {string} type * @param {string} type
* @param {string} download * @param {string} hash
* @param {string=} customSpecSuffix * @param {string=} customSpecSuffix
* @returns {string} * @returns {string}
*/ */
export function attachmentRaw(type, download, customSpecSuffix) { export function serverRequestRaw(type, hash, customSpecSuffix) {
customSpecSuffix = undefined === customSpecSuffix ? getHash() : customSpecSuffix; return SERVER_PREFIX + '/Raw/' + SUB_QUERY_PREFIX + '/'
return ( + (null == customSpecSuffix ? getHash() : customSpecSuffix) + '/'
SERVER_PREFIX + + (type
'/Raw/' + ? type + '/' + (hash ? SUB_QUERY_PREFIX + '/' + hash : '')
SUB_QUERY_PREFIX + : '')
'/' + ;
customSpecSuffix +
'/' +
type +
'/' +
SUB_QUERY_PREFIX +
'/' +
download
);
} }
/** /**
@ -69,7 +61,7 @@ export function attachmentRaw(type, download, customSpecSuffix) {
* @returns {string} * @returns {string}
*/ */
export function attachmentDownload(download, customSpecSuffix) { 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} * @returns {string}
*/ */
export function attachmentPreview(download, customSpecSuffix) { 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} * @returns {string}
*/ */
export function attachmentThumbnailPreview(download, customSpecSuffix) { 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} * @returns {string}
*/ */
export function attachmentPreviewAsPlain(download, customSpecSuffix) { 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} * @returns {string}
*/ */
export function attachmentFramed(download, customSpecSuffix) { 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} * @returns {string}
*/ */
export function messageViewLink(requestHash) { export function messageViewLink(requestHash) {
return ( return serverRequestRaw('ViewAsPlain', requestHash);
SERVER_PREFIX +
'/Raw/' +
SUB_QUERY_PREFIX +
'/' +
getHash() +
'/ViewAsPlain/' +
SUB_QUERY_PREFIX +
'/' +
requestHash
);
} }
/** /**
@ -175,17 +157,7 @@ export function messageViewLink(requestHash) {
* @returns {string} * @returns {string}
*/ */
export function messageDownloadLink(requestHash) { export function messageDownloadLink(requestHash) {
return ( return serverRequestRaw('Download', requestHash);
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) + '/';
} }
/** /**
@ -201,9 +173,7 @@ export function publicLink(hash) {
* @returns {string} * @returns {string}
*/ */
export function userBackground(hash) { export function userBackground(hash) {
return ( return serverRequestRaw('UserBackground', hash);
SERVER_PREFIX + '/Raw/' + SUB_QUERY_PREFIX + '/' + getHash() + '/UserBackground/' + SUB_QUERY_PREFIX + '/' + hash
);
} }
/** /**
@ -219,14 +189,14 @@ export function langLink(lang, isAdmin) {
* @returns {string} * @returns {string}
*/ */
export function exportContactsVcf() { export function exportContactsVcf() {
return SERVER_PREFIX + '/Raw/' + SUB_QUERY_PREFIX + '/' + getHash() + '/ContactsVcf/'; return serverRequestRaw('ContactsVcf');
} }
/** /**
* @returns {string} * @returns {string}
*/ */
export function exportContactsCsv() { 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'); return staticPrefix('js/min/openpgp.worker.min.js');
} }
/**
* @returns {string}
*/
export function openPgpWorkerPath() {
return staticPrefix('js/min/');
}
/** /**
* @param {string} theme * @param {string} theme
* @returns {string} * @returns {string}
@ -303,13 +266,6 @@ export function settings(screenName = '') {
return HASH_PREFIX + 'settings' + (screenName ? '/' + screenName : ''); return HASH_PREFIX + 'settings' + (screenName ? '/' + screenName : '');
} }
/**
* @returns {string}
*/
export function about() {
return HASH_PREFIX + 'about';
}
/** /**
* @param {string} screenName * @param {string} screenName
* @returns {string} * @returns {string}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,9 +1,9 @@
const config = { const config = {
'title': false, title: false,
'stylesSet': false, stylesSet: false,
'customConfig': '', customConfig: '',
'contentsCss': '', contentsCss: '',
'toolbarGroups': [ toolbarGroups: [
{ name: 'spec' }, { name: 'spec' },
{ name: 'styles' }, { name: 'styles' },
{ name: 'basicstyles', groups: ['basicstyles', 'cleanup', 'bidi'] }, { name: 'basicstyles', groups: ['basicstyles', 'cleanup', 'bidi'] },
@ -15,85 +15,56 @@ const config = {
{ name: 'others' } { name: 'others' }
], ],
'removePlugins': 'liststyle', removePlugins: 'liststyle',
'removeButtons': 'Format,Undo,Redo,Cut,Copy,Paste,Anchor,Strike,Subscript,Superscript,Image,SelectAll,Source', removeButtons: 'Format,Undo,Redo,Cut,Copy,Paste,Anchor,Strike,Subscript,Superscript,Image,SelectAll',
'removeDialogTabs': 'link:advanced;link:target;image:advanced;images:advanced', removeDialogTabs: 'link:advanced;link:target;image:advanced;images:advanced',
'extraPlugins': 'plain,signature', extraPlugins: 'plain,signature',
'allowedContent': true, allowedContent: true,
'extraAllowedContent': true, extraAllowedContent: true,
'fillEmptyBlocks': false, fillEmptyBlocks: false,
'ignoreEmptyParagraph': true, ignoreEmptyParagraph: true,
'disableNativeSpellChecker': false, disableNativeSpellChecker: false,
'colorButton_enableAutomatic': false, colorButton_enableAutomatic: false,
'colorButton_enableMore': true, colorButton_enableMore: true,
'font_defaultLabel': 'Arial', font_defaultLabel: 'Arial',
'fontSize_defaultLabel': '13', 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' 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 = { htmlEditorLangsMap = {
'ar_sa': 'ar-sa', '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_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_cn': 'zh-cn',
'zh_tw': 'zh'
}; };
export function createCKEditor(element) export function createCKEditor(element)
{ {
const language = rl.settings.get('Language'), const language = (rl.settings.get('Language') || 'en').toLowerCase(),
allowSource = !!rl.settings.app('allowHtmlEditorSourceButton'), noSource = !rl.settings.app('allowHtmlEditorSourceButton'),
biti = !!rl.settings.app('allowHtmlEditorBitiButtons'); noBidi = !rl.settings.app('allowHtmlEditorBitiButtons');
if ((allowSource || !biti) && !config.toolbarGroups.__cfgInited) { if (!config.__cfgInited) {
config.toolbarGroups.__cfgInited = true; config.__cfgInited = true;
if (allowSource) { if (noSource) {
config.removeButtons = config.removeButtons.replace(',Source', ''); config.removeButtons += ',Source';
} }
if (!biti) { if (noBidi) {
config.removePlugins += (config.removePlugins ? ',' : '') + 'bidi'; config.removePlugins += ',bidi';
} }
} }
config.enterMode = CKEDITOR.ENTER_BR; config.enterMode = CKEDITOR.ENTER_BR;
config.shiftEnterMode = CKEDITOR.ENTER_P; config.shiftEnterMode = CKEDITOR.ENTER_P;
config.language = htmlEditorLangsMap[(language || 'en').toLowerCase()] || 'en'; config.language = htmlEditorLangsMap[language] || language.substr(0,2);
if (CKEDITOR.env) { if (CKEDITOR.env) {
CKEDITOR.env.isCompatible = true; CKEDITOR.env.isCompatible = true;
} }
@ -112,12 +83,10 @@ export function createCKEditor(element)
reader = new FileReader(); reader = new FileReader();
reader.onloadend = () => { reader.onloadend = () => {
if (reader.result) { if (reader.result && 'wysiwyg' === editor.mode) {
if ('wysiwyg' === editor.mode) { try {
try { editor.setData(editor.getData().replace(imageId, `<img src="${reader.result}" />`));
editor.setData(editor.getData().replace(imageId, `<img src="${reader.result}" />`)); } catch (e) {} // eslint-disable-line no-empty
} catch (e) {} // eslint-disable-line no-empty
}
} }
}; };

View file

@ -3,6 +3,7 @@ import ko from 'ko';
import { HtmlEditor } from 'Common/Html'; import { HtmlEditor } from 'Common/Html';
import { timeToNode } from 'Common/Momentor'; import { timeToNode } from 'Common/Momentor';
import { EmailModel } from 'Model/Email'; import { EmailModel } from 'Model/Email';
import { doc } from 'Common/Globals';
const rlContentType = 'snappymail/action', const rlContentType = 'snappymail/action',
@ -111,7 +112,7 @@ ko.bindingHandlers.dragmessages = {
if (!rl.settings.app('mobile')) { if (!rl.settings.app('mobile')) {
element.addEventListener("dragstart", e => { element.addEventListener("dragstart", e => {
let data = fValueAccessor()(e); let data = fValueAccessor()(e);
dragImage || (dragImage = document.getElementById('messagesDragImage')); dragImage || (dragImage = doc.getElementById('messagesDragImage'));
if (data && dragImage) { if (data && dragImage) {
dragImage.querySelector('.text').textContent = data.uids.length; dragImage.querySelector('.text').textContent = data.uids.length;
let img = dragImage.querySelector('.icon-white'); 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 { i18n, i18nToNodes, trigger } from 'Common/Translator';
import { dropdownVisibility } from 'Common/Globals'; import { doc, dropdownVisibility } from 'Common/Globals';
const const
doc = document,
isFunction = v => typeof v === 'function', isFunction = v => typeof v === 'function',
koValue = value => !ko.isObservable(value) && isFunction(value) ? value() : ko.unwrap(value); koValue = value => !ko.isObservable(value) && isFunction(value) ? value() : ko.unwrap(value);

View file

@ -39,15 +39,18 @@ export class AbstractScreen {
/** /**
* @returns {void} * @returns {void}
*/ */
__start() { onStart() {
const routes = this.routes(); if (!this.__started) {
if (Array.isNotEmpty(routes)) { this.__started = true;
let route = new Crossroads(), const routes = this.routes();
fMatcher = (this.onRoute || (()=>{})).bind(this); if (Array.isNotEmpty(routes)) {
let route = new Crossroads(),
fMatcher = (this.onRoute || (()=>{})).bind(this);
routes.forEach(item => item && route && (route.addRoute(item[0], fMatcher).rules = item[1])); routes.forEach(item => item && route && (route.addRoute(item[0], fMatcher).rules = item[1]));
this.oCross = route; this.oCross = route;
}
} }
} }
} }

View file

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

View file

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

View file

@ -2,6 +2,7 @@ import ko from 'ko';
import { pString } from 'Common/Utils'; import { pString } from 'Common/Utils';
import { settings } from 'Common/Links'; import { settings } from 'Common/Links';
import { doc } from 'Common/Globals';
import { AbstractScreen } from 'Knoin/AbstractScreen'; import { AbstractScreen } from 'Knoin/AbstractScreen';
@ -44,7 +45,7 @@ export class AbstractSettingsScreen extends AbstractScreen {
if (RoutedSettingsViewModel.__builded && RoutedSettingsViewModel.__vm) { if (RoutedSettingsViewModel.__builded && RoutedSettingsViewModel.__vm) {
settingsScreen = RoutedSettingsViewModel.__vm; settingsScreen = RoutedSettingsViewModel.__vm;
} else { } else {
const vmPlace = document.getElementById('rl-settings-subscreen'); const vmPlace = doc.getElementById('rl-settings-subscreen');
if (vmPlace) { if (vmPlace) {
settingsScreen = new RoutedSettingsViewModel(); 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); }, 1);

View file

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

View file

@ -1,5 +1,5 @@
import { Capa, KeyState } from 'Common/Enums'; 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 { runSettingsViewModelHooks } from 'Common/Plugins';
import { initOnStartOrLangChange, i18n } from 'Common/Translator'; 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 { MenuSettingsUserView } from 'View/User/Settings/Menu';
import { PaneSettingsUserView } from 'View/User/Settings/Pane'; import { PaneSettingsUserView } from 'View/User/Settings/Pane';
const Settings = rl.settings;
export class SettingsUserScreen extends AbstractSettingsScreen { export class SettingsUserScreen extends AbstractSettingsScreen {
constructor() { constructor() {
super([SystemDropDownSettingsUserView, MenuSettingsUserView, PaneSettingsUserView]); super([SystemDropDownSettingsUserView, MenuSettingsUserView, PaneSettingsUserView]);

View file

@ -14,7 +14,7 @@ import { showScreenPopup } from 'Knoin/Knoin';
import Remote from 'Remote/Admin/Fetch'; import Remote from 'Remote/Admin/Fetch';
import ThemeStore from 'Stores/Theme'; import { ThemeStore } from 'Stores/Theme';
import LanguageStore from 'Stores/Language'; import LanguageStore from 'Stores/Language';
import AppAdminStore from 'Stores/Admin/App'; import AppAdminStore from 'Stores/Admin/App';
import CapaAdminStore from 'Stores/Admin/Capa'; 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 { changeTheme, convertThemeName } from 'Common/Utils';
import { userBackground, themePreviewLink, uploadBackground } from 'Common/Links'; import { userBackground, themePreviewLink, uploadBackground } from 'Common/Links';
import { i18n } from 'Common/Translator'; 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'; import Remote from 'Remote/User/Fetch';
@ -39,13 +40,12 @@ export class ThemesUserSettings {
}); });
this.background.hash.subscribe((value) => { this.background.hash.subscribe((value) => {
const b = document.body, cl = document.documentElement.classList;
if (!value) { if (!value) {
cl.remove('UserBackground'); $htmlCL.remove('UserBackground');
b.removeAttribute('style'); doc.body.removeAttribute('style');
} else { } else {
cl.add('UserBackground'); $htmlCL.add('UserBackground');
b.style.backgroundImage = "url("+userBackground(value)+")"; doc.body.style.backgroundImage = "url("+userBackground(value)+")";
} }
}); });
} }

View file

@ -1,15 +1,11 @@
import ko from 'ko'; import ko from 'ko';
class ThemeStore { export const ThemeStore = {
constructor() { themes: ko.observableArray(),
this.themes = ko.observableArray(); themeBackgroundName: ko.observable(''),
this.themeBackgroundName = ko.observable(''); themeBackgroundHash: ko.observable(''),
this.themeBackgroundHash = ko.observable('');
this.theme = ko.observable('').extend({ limitedList: this.themes }); populate: function(){
}
populate() {
const Settings = rl.settings, const Settings = rl.settings,
themes = Settings.app('themes'); themes = Settings.app('themes');
@ -18,6 +14,6 @@ class ThemeStore {
this.themeBackgroundName(Settings.get('UserBackgroundName')); this.themeBackgroundName(Settings.get('UserBackgroundName'));
this.themeBackgroundHash(Settings.get('UserBackgroundHash')); 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 { KeyState } from 'Common/Enums';
import { Focused } from 'Common/EnumsUser'; import { Focused } from 'Common/EnumsUser';
import { keyScope, leftPanelDisabled } from 'Common/Globals'; import { keyScope, leftPanelDisabled, Settings } from 'Common/Globals';
const Settings = rl.settings;
class AppUserStore { class AppUserStore {
constructor() { constructor() {

View file

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

View file

@ -2,6 +2,7 @@ import ko from 'ko';
import { i18n } from 'Common/Translator'; import { i18n } from 'Common/Translator';
import { pString } from 'Common/Utils'; import { pString } from 'Common/Utils';
import { doc } from 'Common/Globals';
import AccountStore from 'Stores/User/Account'; import AccountStore from 'Stores/User/Account';
@ -360,7 +361,7 @@ class PgpUserStore {
verControl.addEventHandler('click', domControlSignedClickHelper(this, dom, domText)); 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 { MESSAGES_PER_PAGE_VALUES } from 'Common/Consts';
import { Layout, EditorDefaultType } from 'Common/EnumsUser'; import { Layout, EditorDefaultType } from 'Common/EnumsUser';
import { pInt } from 'Common/Utils'; import { pInt } from 'Common/Utils';
import { doc } from 'Common/Globals';
class SettingsUserStore { class SettingsUserStore {
constructor() { constructor() {
@ -39,7 +40,7 @@ class SettingsUserStore {
} }
subscribers() { subscribers() {
const htmlCL = document.documentElement.classList; const htmlCL = doc.documentElement.classList;
this.layout.subscribe(value => { this.layout.subscribe(value => {
htmlCL.toggle('rl-no-preview-pane', Layout.NoPreview === value); htmlCL.toggle('rl-no-preview-pane', Layout.NoPreview === value);
htmlCL.toggle('rl-side-preview-pane', Layout.SidePreview === value); htmlCL.toggle('rl-side-preview-pane', Layout.SidePreview === value);

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -16,7 +16,7 @@ import {
MessageSetAction MessageSetAction
} from 'Common/EnumsUser'; } 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 { inFocus } from 'Common/Utils';
import { mailToHelper } from 'Common/UtilsUser'; import { mailToHelper } from 'Common/UtilsUser';
@ -43,8 +43,6 @@ import { AbstractViewRight } from 'Knoin/AbstractViews';
import { ComposePopupView } from 'View/Popup/Compose'; import { ComposePopupView } from 'View/Popup/Compose';
const Settings = rl.settings;
function isTransparent(color) { function isTransparent(color) {
return 'rgba(0, 0, 0, 0)' === color || 'transparent' === 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 Enums from 'Common/Enums';
import * as Plugins from 'Common/Plugins'; import * as Plugins from 'Common/Plugins';
import { i18n } from 'Common/Translator'; import { i18n } from 'Common/Translator';
@ -38,7 +38,6 @@ export default (App) => {
rl.addSettingsViewModel = Plugins.addSettingsViewModel; rl.addSettingsViewModel = Plugins.addSettingsViewModel;
rl.addSettingsViewModelForAdmin = Plugins.addSettingsViewModelForAdmin; rl.addSettingsViewModelForAdmin = Plugins.addSettingsViewModelForAdmin;
rl.settingsGet = Plugins.mainSettingsGet;
rl.pluginSettingsGet = Plugins.settingsGet; rl.pluginSettingsGet = Plugins.settingsGet;
rl.pluginRemoteRequest = Plugins.remoteRequest; rl.pluginRemoteRequest = Plugins.remoteRequest;
@ -140,8 +139,7 @@ export default (App) => {
}; };
window.__APP_BOOT = fErrorCallback => { window.__APP_BOOT = fErrorCallback => {
const doc = document, const cb = () => setTimeout(() => {
cb = () => setTimeout(() => {
if (rl.TEMPLATES) { if (rl.TEMPLATES) {
doc.getElementById('rl-templates').innerHTML = rl.TEMPLATES; doc.getElementById('rl-templates').innerHTML = rl.TEMPLATES;
setTimeout(() => App.bootstart(), 10); setTimeout(() => App.bootstart(), 10);

View file

@ -1,18 +1,12 @@
$(function () { if (!/iphone|ipod|ipad|android/i.test(navigator.userAgent))
if (window.snowFall && window.rl && !window.rl.settingsGet('Auth')) {
{ document.addEventListener('DOMContentLoaded', () => {
var if (window.snowFall && window.rl && !rl.settings.get('Auth'))
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)
{ {
window.snowFall.snow(document.getElementsByTagName('body'), { window.snowFall.snow(document.getElementsByTagName('body'), {
shadow: true, round: true, minSize: 2, maxSize: 5 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_LIST: "Can't get message list"
CANT_GET_MESSAGE: "Can't get message" CANT_GET_MESSAGE: "Can't get message"
CANT_DELETE_MESSAGE: "Can't delete message" CANT_DELETE_MESSAGE: "Can't delete message"
CANT_COPY_MESSAGE: "Can't copy message"
CANT_MOVE_MESSAGE: "Can't move message" CANT_MOVE_MESSAGE: "Can't move message"
CANT_SAVE_MESSAGE: "Can't save message" CANT_SAVE_MESSAGE: "Can't save message"
CANT_SEND_MESSAGE: "Can't send 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_LIST: "Die Nachrichtenliste ist nicht verfügbar"
CANT_GET_MESSAGE: "Diese Nachricht ist nicht verfügbar" CANT_GET_MESSAGE: "Diese Nachricht ist nicht verfügbar"
CANT_DELETE_MESSAGE: "Diese Nachricht kann nicht gelöscht werden" 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_MOVE_MESSAGE: "Diese Nachricht kann nicht verschoben werden"
CANT_SAVE_MESSAGE: "Diese Nachricht kann nicht gespeichert werden" CANT_SAVE_MESSAGE: "Diese Nachricht kann nicht gespeichert werden"
CANT_SEND_MESSAGE: "Diese Nachricht kann nicht gesendet 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_LIST: "Can't get message list"
CANT_GET_MESSAGE: "Can't get message" CANT_GET_MESSAGE: "Can't get message"
CANT_DELETE_MESSAGE: "Can't delete message" CANT_DELETE_MESSAGE: "Can't delete message"
CANT_COPY_MESSAGE: "Can't copy message"
CANT_MOVE_MESSAGE: "Can't move message" CANT_MOVE_MESSAGE: "Can't move message"
CANT_SAVE_MESSAGE: "Can't save message" CANT_SAVE_MESSAGE: "Can't save message"
CANT_SEND_MESSAGE: "Can't send 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_LIST: "No se puede obtener la lista de mensajes"
CANT_GET_MESSAGE: "No se puede obtener el mensaje" CANT_GET_MESSAGE: "No se puede obtener el mensaje"
CANT_DELETE_MESSAGE: "No se puede eliminar 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_MOVE_MESSAGE: "No se puede mover el mensaje"
CANT_SAVE_MESSAGE: "No se puede guardar el mensaje" CANT_SAVE_MESSAGE: "No se puede guardar el mensaje"
CANT_SEND_MESSAGE: "No se puede enviar 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_LIST: "Impossible d'obtenir la liste des messages"
CANT_GET_MESSAGE: "Impossible d'obtenir le message" CANT_GET_MESSAGE: "Impossible d'obtenir le message"
CANT_DELETE_MESSAGE: "Impossible de supprimer 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_MOVE_MESSAGE: "Impossible de déplacer le message"
CANT_SAVE_MESSAGE: "Impossible d'enregistrer le message" CANT_SAVE_MESSAGE: "Impossible d'enregistrer le message"
CANT_SEND_MESSAGE: "Impossible d'envoyer 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_LIST: "Kan berichtenlijst niet ophalen"
CANT_GET_MESSAGE: "Kan bericht niet ophalen" CANT_GET_MESSAGE: "Kan bericht niet ophalen"
CANT_DELETE_MESSAGE: "Kan bericht niet verwijderen" CANT_DELETE_MESSAGE: "Kan bericht niet verwijderen"
CANT_COPY_MESSAGE: "Kan bericht niet kopiëren"
CANT_MOVE_MESSAGE: "Kan bericht niet verplaatsen" CANT_MOVE_MESSAGE: "Kan bericht niet verplaatsen"
CANT_SAVE_MESSAGE: "Kan bericht niet opslaan" CANT_SAVE_MESSAGE: "Kan bericht niet opslaan"
CANT_SEND_MESSAGE: "Kan bericht niet verzenden" CANT_SEND_MESSAGE: "Kan bericht niet verzenden"

View file

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

View file

@ -523,6 +523,7 @@ en:
CANT_GET_MESSAGE_LIST: "Can't get message list" CANT_GET_MESSAGE_LIST: "Can't get message list"
CANT_GET_MESSAGE: "Can't get message" CANT_GET_MESSAGE: "Can't get message"
CANT_DELETE_MESSAGE: "Can't delete message" CANT_DELETE_MESSAGE: "Can't delete message"
CANT_COPY_MESSAGE: "Can't copy message"
CANT_MOVE_MESSAGE: "Can't move message" CANT_MOVE_MESSAGE: "Can't move message"
CANT_SAVE_MESSAGE: "Can't save message" CANT_SAVE_MESSAGE: "Can't save message"
CANT_SEND_MESSAGE: "Can't send 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_LIST: "Die Nachrichtenliste ist nicht verfügbar"
CANT_GET_MESSAGE: "Diese Nachricht ist nicht verfügbar" CANT_GET_MESSAGE: "Diese Nachricht ist nicht verfügbar"
CANT_DELETE_MESSAGE: "Diese Nachricht kann nicht gelöscht werden" 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_MOVE_MESSAGE: "Diese Nachricht kann nicht verschoben werden"
CANT_SAVE_MESSAGE: "Diese Nachricht kann nicht gespeichert werden" CANT_SAVE_MESSAGE: "Diese Nachricht kann nicht gespeichert werden"
CANT_SEND_MESSAGE: "Diese Nachricht kann nicht gesendet 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_LIST: "Can't get message list"
CANT_GET_MESSAGE: "Can't get message" CANT_GET_MESSAGE: "Can't get message"
CANT_DELETE_MESSAGE: "Can't delete message" CANT_DELETE_MESSAGE: "Can't delete message"
CANT_COPY_MESSAGE: "Can't copy message"
CANT_MOVE_MESSAGE: "Can't move message" CANT_MOVE_MESSAGE: "Can't move message"
CANT_SAVE_MESSAGE: "Can't save message" CANT_SAVE_MESSAGE: "Can't save message"
CANT_SEND_MESSAGE: "Can't send 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_LIST: "Can't get message list"
CANT_GET_MESSAGE: "Can't get message" CANT_GET_MESSAGE: "Can't get message"
CANT_DELETE_MESSAGE: "Can't delete message" CANT_DELETE_MESSAGE: "Can't delete message"
CANT_COPY_MESSAGE: "Can't copy message"
CANT_MOVE_MESSAGE: "Can't move message" CANT_MOVE_MESSAGE: "Can't move message"
CANT_SAVE_MESSAGE: "Can't save message" CANT_SAVE_MESSAGE: "Can't save message"
CANT_SEND_MESSAGE: "Can't send 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_LIST: "No se puede obtener la lista de mensajes"
CANT_GET_MESSAGE: "No se puede obtener el mensaje" CANT_GET_MESSAGE: "No se puede obtener el mensaje"
CANT_DELETE_MESSAGE: "No se puede eliminar 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_MOVE_MESSAGE: "No se puede mover el mensaje"
CANT_SAVE_MESSAGE: "No se puede guardar el mensaje" CANT_SAVE_MESSAGE: "No se puede guardar el mensaje"
CANT_SEND_MESSAGE: "No se puede enviar 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_LIST: "Impossible d'obtenir la liste des messages"
CANT_GET_MESSAGE: "Impossible d'obtenir le message" CANT_GET_MESSAGE: "Impossible d'obtenir le message"
CANT_DELETE_MESSAGE: "Impossible de supprimer 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_MOVE_MESSAGE: "Impossible de déplacer le message"
CANT_SAVE_MESSAGE: "Impossible d'enregistrer le message" CANT_SAVE_MESSAGE: "Impossible d'enregistrer le message"
CANT_SEND_MESSAGE: "Impossible d'envoyer 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_LIST: "Berichtenlijst kan niet worden opgehaald"
CANT_GET_MESSAGE: "Bericht kan niet worden opgehaald" CANT_GET_MESSAGE: "Bericht kan niet worden opgehaald"
CANT_DELETE_MESSAGE: "Kan bericht niet verwijderen" CANT_DELETE_MESSAGE: "Kan bericht niet verwijderen"
CANT_COPY_MESSAGE: "Kan bericht niet kopiëren"
CANT_MOVE_MESSAGE: "Kan bericht niet verplaatsen" CANT_MOVE_MESSAGE: "Kan bericht niet verplaatsen"
CANT_SAVE_MESSAGE: "Kan bericht niet opslaan" CANT_SAVE_MESSAGE: "Kan bericht niet opslaan"
CANT_SEND_MESSAGE: "Kan bericht niet verzenden" CANT_SEND_MESSAGE: "Kan bericht niet verzenden"

View file

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