mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-08-25 10:09:20 +03:00
Improve scripts load system
This commit is contained in:
parent
58b9eed8e8
commit
72bf212f67
39 changed files with 916 additions and 411 deletions
|
|
@ -23,7 +23,7 @@ class AbstractApp extends AbstractBoot
|
||||||
{
|
{
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this.iframe = $('<iframe style="display:none" src="javascript:;" />').appendTo('body');
|
this.iframe = $('<iframe style="display:none" />').appendTo('body');
|
||||||
|
|
||||||
Globals.$win.on('error', function (oEvent) {
|
Globals.$win.on('error', function (oEvent) {
|
||||||
if (oEvent && oEvent.originalEvent && oEvent.originalEvent.message &&
|
if (oEvent && oEvent.originalEvent && oEvent.originalEvent.message &&
|
||||||
|
|
|
||||||
|
|
@ -1213,13 +1213,6 @@ class AppUser extends AbstractApp
|
||||||
{
|
{
|
||||||
kn.hideLoading();
|
kn.hideLoading();
|
||||||
|
|
||||||
progressJs.onbeforeend(() => {
|
|
||||||
$('.progressjs-container').hide();
|
|
||||||
_.delay(() => {
|
|
||||||
$('.progressjs-container').remove();
|
|
||||||
}, 100);
|
|
||||||
});
|
|
||||||
|
|
||||||
progressJs.set(100).end();
|
progressJs.set(100).end();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -1239,7 +1232,6 @@ class AppUser extends AbstractApp
|
||||||
require('Stores/User/Contact').populate();
|
require('Stores/User/Contact').populate();
|
||||||
|
|
||||||
var
|
var
|
||||||
$LAB = require('$LAB'),
|
|
||||||
sJsHash = Settings.appSettingsGet('jsHash'),
|
sJsHash = Settings.appSettingsGet('jsHash'),
|
||||||
sStartupUrl = Utils.pString(Settings.settingsGet('StartupUrl')),
|
sStartupUrl = Utils.pString(Settings.settingsGet('StartupUrl')),
|
||||||
iContactsSyncInterval = Utils.pInt(Settings.settingsGet('ContactsSyncInterval')),
|
iContactsSyncInterval = Utils.pInt(Settings.settingsGet('ContactsSyncInterval')),
|
||||||
|
|
@ -1288,7 +1280,7 @@ class AppUser extends AbstractApp
|
||||||
kn.routeOn();
|
kn.routeOn();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($LAB && window.crypto && window.crypto.getRandomValues && Settings.capa(Enums.Capa.OpenPGP))
|
if (window.jsloader && window.crypto && window.crypto.getRandomValues && Settings.capa(Enums.Capa.OpenPGP))
|
||||||
{
|
{
|
||||||
const openpgpCallback = (openpgp) => {
|
const openpgpCallback = (openpgp) => {
|
||||||
|
|
||||||
|
|
@ -1298,8 +1290,7 @@ class AppUser extends AbstractApp
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// PgpStore.openpgp.initWorker(Links.openPgpWorkerJs()); // 1.2.0
|
PgpStore.openpgp.initWorker({path: Links.openPgpWorkerJs()});
|
||||||
PgpStore.openpgp.initWorker({path: Links.openPgpWorkerJs()}); // 2.3.0
|
|
||||||
}
|
}
|
||||||
catch (e)
|
catch (e)
|
||||||
{
|
{
|
||||||
|
|
@ -1321,7 +1312,7 @@ class AppUser extends AbstractApp
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
$LAB.script(Links.openPgpJs()).wait(() => {
|
window.jsloader(Links.openPgpJs()).then(() => {
|
||||||
if (window.openpgp)
|
if (window.openpgp)
|
||||||
{
|
{
|
||||||
openpgpCallback(window.openpgp);
|
openpgpCallback(window.openpgp);
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,20 @@
|
||||||
|
|
||||||
import window from 'window';
|
import window from 'window';
|
||||||
import $ from '$';
|
import $ from '$';
|
||||||
|
import progressJs from 'progressJs';
|
||||||
|
|
||||||
import rainLoopStorage from 'Storage/RainLoop';
|
import rainLoopStorage from 'Storage/RainLoop';
|
||||||
|
|
||||||
|
let rlAppDataStorage = null;
|
||||||
|
|
||||||
window.__rlah = () => {
|
window.__rlah = () => {
|
||||||
return rainLoopStorage ? rainLoopStorage.getHash() : null;
|
return rainLoopStorage ? rainLoopStorage.getHash() : null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
window.__rlah_data = () => {
|
||||||
|
return rlAppDataStorage;
|
||||||
|
};
|
||||||
|
|
||||||
window.__rlah_set = () => {
|
window.__rlah_set = () => {
|
||||||
if (rainLoopStorage)
|
if (rainLoopStorage)
|
||||||
{
|
{
|
||||||
|
|
@ -22,20 +29,59 @@ window.__rlah_clear = () => {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
window.__includeScr = (src) => {
|
function includeStyle(styles)
|
||||||
window.document.write(unescape('%3Csc' + 'ript data-cfasync="false" type="text/jav' + 'ascr' + 'ipt" sr' + 'c="' + src + '"%3E%3C/' + 'scr' + 'ipt%3E'));
|
{
|
||||||
};
|
|
||||||
|
|
||||||
window.__includeAppScr = (src) => {
|
|
||||||
window.__includeScr(src + (window.__rlah ? window.__rlah() || '0' : '0') + '/' + window.Math.random().toString().substr(2) + '/');
|
|
||||||
};
|
|
||||||
|
|
||||||
window.__includeStyle = (styles) => {
|
|
||||||
window.document.write(unescape('%3Csty' + 'le%3E' + styles + '"%3E%3C/' + 'sty' + 'le%3E'));
|
window.document.write(unescape('%3Csty' + 'le%3E' + styles + '"%3E%3C/' + 'sty' + 'le%3E'));
|
||||||
};
|
}
|
||||||
|
|
||||||
window.__showError = (additionalError) => {
|
function includeScr(src)
|
||||||
|
{
|
||||||
|
window.document.write(unescape('%3Csc' + 'ript type="text/jav' + 'ascr' + 'ipt" data-cfasync="false" sr' + 'c="' + src + '"%3E%3C/' + 'scr' + 'ipt%3E'));
|
||||||
|
}
|
||||||
|
|
||||||
|
function includeLayout()
|
||||||
|
{
|
||||||
|
const
|
||||||
|
layout = require('Html/Layout.html'),
|
||||||
|
app = window.document.getElementById('rl-app')
|
||||||
|
;
|
||||||
|
|
||||||
|
if (app && layout)
|
||||||
|
{
|
||||||
|
app.innerHTML = layout.replace(/[\r\n\t]+/g, '');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function includeAppScr(data = {})
|
||||||
|
{
|
||||||
|
let src = './?/';
|
||||||
|
src += data.admin ? 'Admin' : '';
|
||||||
|
src += 'AppData@';
|
||||||
|
src += data.mobile ? 'mobile' : 'no-mobile';
|
||||||
|
src += data.mobileDevice ? '-1' : '-0';
|
||||||
|
src += '/';
|
||||||
|
|
||||||
|
includeScr(src + (window.__rlah ? window.__rlah() || '0' : '0') + '/' + window.Math.random().toString().substr(2) + '/');
|
||||||
|
}
|
||||||
|
|
||||||
|
function getRainloopBootData()
|
||||||
|
{
|
||||||
|
let result = {};
|
||||||
|
const meta = window.document.getElementById('app-boot-data');
|
||||||
|
|
||||||
|
if (meta && meta.getAttribute)
|
||||||
|
{
|
||||||
|
result = JSON.parse(meta.getAttribute('content')) || {};
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function showError(additionalError)
|
||||||
|
{
|
||||||
const
|
const
|
||||||
oR = window.document.getElementById('rl-loading'),
|
oR = window.document.getElementById('rl-loading'),
|
||||||
oL = window.document.getElementById('rl-loading-error'),
|
oL = window.document.getElementById('rl-loading-error'),
|
||||||
|
|
@ -58,14 +104,14 @@ window.__showError = (additionalError) => {
|
||||||
oLA.innerHTML = additionalError;
|
oLA.innerHTML = additionalError;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (window.rainloopProgressJs)
|
if (progressJs)
|
||||||
{
|
{
|
||||||
window.rainloopProgressJs.set(100);
|
progressJs.set(100).end();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
window.__showDescription = (description) => {
|
|
||||||
|
|
||||||
|
function showDescriptionAndLoading(description)
|
||||||
|
{
|
||||||
const
|
const
|
||||||
oE = window.document.getElementById('rl-loading'),
|
oE = window.document.getElementById('rl-loading'),
|
||||||
oElDesc = window.document.getElementById('rl-loading-desc')
|
oElDesc = window.document.getElementById('rl-loading-desc')
|
||||||
|
|
@ -83,76 +129,81 @@ window.__showDescription = (description) => {
|
||||||
oE.style.opacity = 1;
|
oE.style.opacity = 1;
|
||||||
}, 300);
|
}, 300);
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
window.__runBoot = (withError, additionalError) => {
|
function runMainBoot(withError, additionalError)
|
||||||
if (window.__APP_BOOT && !withError) {
|
{
|
||||||
|
if (window.__APP_BOOT && !withError)
|
||||||
|
{
|
||||||
window.__APP_BOOT(function (bV) {
|
window.__APP_BOOT(function (bV) {
|
||||||
if (!bV) {
|
if (!bV)
|
||||||
window.__showError(additionalError);
|
{
|
||||||
|
showError(additionalError);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
|
||||||
window.__showError(additionalError);
|
|
||||||
}
|
}
|
||||||
};
|
else
|
||||||
|
|
||||||
window.__runApp = (BaseAppLibsScriptLink, BaseAppMainScriptLink, BaseAppEditorScriptLink) => {
|
|
||||||
|
|
||||||
const appData = window.rainloopAppData;
|
|
||||||
|
|
||||||
if (window.$LAB && window.progressJs && appData && appData.TemplatesLink && appData.LangLink)
|
|
||||||
{
|
{
|
||||||
const p = window.progressJs();
|
showError(additionalError);
|
||||||
window.rainloopProgressJs = p;
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function runApp()
|
||||||
|
{
|
||||||
|
const appData = window.__rlah_data();
|
||||||
|
|
||||||
|
if (window.jsloader && progressJs && appData && appData.TemplatesLink && appData.LangLink &&
|
||||||
|
appData.StaticLibJsLink && appData.StaticAppJsLink && appData.StaticEditorJsLink)
|
||||||
|
{
|
||||||
|
const p = progressJs;
|
||||||
|
|
||||||
p.setOptions({theme: 'rainloop'});
|
p.setOptions({theme: 'rainloop'});
|
||||||
p.start().set(5);
|
p.start().set(5);
|
||||||
|
|
||||||
window.$LAB
|
const
|
||||||
.script(function () {
|
libs = window.jsloader(appData.StaticLibJsLink).then(() => {
|
||||||
return [
|
if (window.$)
|
||||||
{src: BaseAppLibsScriptLink, type: 'text/javascript', charset: 'utf-8'}
|
{
|
||||||
];
|
if (!window.$('#rl-check').is(':visible'))
|
||||||
})
|
{
|
||||||
.wait(function () {
|
window.$('html').addClass('no-css');
|
||||||
|
throw new Error('no-css');
|
||||||
|
}
|
||||||
|
|
||||||
p.set(20);
|
window.$('#rl-check').remove();
|
||||||
|
|
||||||
if (appData.IncludeBackground && $) {
|
if (appData.IncludeBackground)
|
||||||
$('#rl-bg').attr('style', 'background-image: none !important;')
|
{
|
||||||
|
window.$('#rl-bg').attr('style', 'background-image: none !important;')
|
||||||
.backstretch(appData.IncludeBackground.replace('{{USER}}',
|
.backstretch(appData.IncludeBackground.replace('{{USER}}',
|
||||||
(window.__rlah ? window.__rlah() || '0' : '0')), {fade: 100, centeredX: true, centeredY: true})
|
(window.__rlah ? (window.__rlah() || '0') : '0')), {fade: 100, centeredX: true, centeredY: true})
|
||||||
.removeAttr('style')
|
.removeAttr('style')
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
.script(function () {
|
}),
|
||||||
return [
|
common = window.Promise.all([
|
||||||
{src: appData.TemplatesLink, type: 'text/javascript', charset: 'utf-8'},
|
window.jsloader(appData.TemplatesLink),
|
||||||
{src: appData.LangLink, type: 'text/javascript', charset: 'utf-8'}
|
window.jsloader(appData.LangLink)
|
||||||
];
|
])
|
||||||
})
|
;
|
||||||
.wait(function () {
|
|
||||||
|
window.Promise.all([libs, common])
|
||||||
|
.then(() => {
|
||||||
p.set(30);
|
p.set(30);
|
||||||
})
|
return window.jsloader(appData.StaticAppJsLink);
|
||||||
.script(function () {
|
}).then(() => {
|
||||||
return {src: BaseAppMainScriptLink, type: 'text/javascript', charset: 'utf-8'};
|
|
||||||
})
|
|
||||||
.wait(function () {
|
|
||||||
p.set(50);
|
p.set(50);
|
||||||
})
|
return appData.PluginsLink ? window.jsloader(appData.PluginsLink) : window.Promise.resolve();
|
||||||
.script(function () {
|
}).then(() => {
|
||||||
return appData.PluginsLink ? {src: appData.PluginsLink, type: 'text/javascript', charset: 'utf-8'} : null;
|
|
||||||
})
|
|
||||||
.wait(function () {
|
|
||||||
p.set(70);
|
p.set(70);
|
||||||
window.__runBoot(false);
|
runMainBoot(false);
|
||||||
})
|
}).catch((e) => {
|
||||||
.script(function () {
|
runMainBoot(true);
|
||||||
return {src: BaseAppEditorScriptLink, type: 'text/javascript', charset: 'utf-8'};
|
throw e;
|
||||||
})
|
}).then(() => {
|
||||||
.wait(function () {
|
return window.jsloader(appData.StaticEditorJsLink);
|
||||||
|
}).then(() => {
|
||||||
if (window.CKEDITOR && window.__initEditor) {
|
if (window.CKEDITOR && window.__initEditor) {
|
||||||
window.__initEditor();
|
window.__initEditor();
|
||||||
window.__initEditor = null;
|
window.__initEditor = null;
|
||||||
|
|
@ -162,6 +213,41 @@ window.__runApp = (BaseAppLibsScriptLink, BaseAppMainScriptLink, BaseAppEditorSc
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
window.__runBoot(true);
|
runMainBoot(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window.__initAppData = function(data) {
|
||||||
|
|
||||||
|
rlAppDataStorage = data;
|
||||||
|
|
||||||
|
window.__rlah_set();
|
||||||
|
|
||||||
|
if (rlAppDataStorage.NewThemeLink)
|
||||||
|
{
|
||||||
|
window.document.getElementById('app-theme-link').href = rlAppDataStorage.NewThemeLink;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rlAppDataStorage.IncludeCss)
|
||||||
|
{
|
||||||
|
includeStyle(rlAppDataStorage.IncludeCss);
|
||||||
|
}
|
||||||
|
|
||||||
|
showDescriptionAndLoading(rlAppDataStorage ? (rlAppDataStorage.LoadingDescriptionEsc || '') : '');
|
||||||
|
|
||||||
|
runApp();
|
||||||
|
};
|
||||||
|
|
||||||
|
window.__runBoot = function() {
|
||||||
|
|
||||||
|
if (!window.navigator || !window.navigator.cookieEnabled)
|
||||||
|
{
|
||||||
|
window.document.location.replace('./?/NoCookie');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (includeLayout())
|
||||||
|
{
|
||||||
|
includeAppScr(getRainloopBootData());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
25
dev/Common/Loader.jsx
Normal file
25
dev/Common/Loader.jsx
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
|
||||||
|
import window from 'window';
|
||||||
|
import {Promise} from 'es6-promise-polyfill/promise.js';
|
||||||
|
|
||||||
|
window.Promise = window.Promise || Promise;
|
||||||
|
|
||||||
|
export default (url) => {
|
||||||
|
return new window.Promise((resolve, reject) => {
|
||||||
|
|
||||||
|
const element = document.createElement('script');
|
||||||
|
|
||||||
|
element.onload = () => {
|
||||||
|
resolve(url);
|
||||||
|
};
|
||||||
|
|
||||||
|
element.onerror = () => {
|
||||||
|
reject(new Error(url));
|
||||||
|
};
|
||||||
|
|
||||||
|
element.async = true;
|
||||||
|
element.src = url;
|
||||||
|
|
||||||
|
document.body.appendChild(element);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
@ -1419,7 +1419,7 @@
|
||||||
aContent.push('' + sKey + '=' + sValue);
|
aContent.push('' + sKey + '=' + sValue);
|
||||||
});
|
});
|
||||||
|
|
||||||
$('#rl-head-viewport').attr('content', aContent.join(', '));
|
$('#app-head-viewport').attr('content', aContent.join(', '));
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -1538,8 +1538,8 @@
|
||||||
Utils.changeTheme = function (sValue, themeTrigger)
|
Utils.changeTheme = function (sValue, themeTrigger)
|
||||||
{
|
{
|
||||||
var
|
var
|
||||||
oThemeLink = $('#rlThemeLink'),
|
oThemeLink = $('#app-theme-link'),
|
||||||
oThemeStyle = $('#rlThemeStyle'),
|
oThemeStyle = $('#app-theme-style'),
|
||||||
sUrl = oThemeLink.attr('href')
|
sUrl = oThemeLink.attr('href')
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
@ -1576,7 +1576,7 @@
|
||||||
{
|
{
|
||||||
if (oThemeLink && oThemeLink[0] && (!oThemeStyle || !oThemeStyle[0]))
|
if (oThemeLink && oThemeLink[0] && (!oThemeStyle || !oThemeStyle[0]))
|
||||||
{
|
{
|
||||||
oThemeStyle = $('<style id="rlThemeStyle"></style>');
|
oThemeStyle = $('<style id="app-theme-style"></style>');
|
||||||
oThemeLink.after(oThemeStyle);
|
oThemeLink.after(oThemeStyle);
|
||||||
oThemeLink.remove();
|
oThemeLink.remove();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
24
dev/Html/Layout.html
Normal file
24
dev/Html/Layout.html
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
<div id="rl-bg" class="thm-body"></div>
|
||||||
|
<div id="rl-loading" class="thm-loading" style="opacity:0">
|
||||||
|
<div id="rl-loading-desc"></div>
|
||||||
|
<div class="e-spinner">
|
||||||
|
<div class="e-bounce bounce1"></div>
|
||||||
|
<div class="e-bounce bounce2"></div>
|
||||||
|
<div class="e-bounce bounce3"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="rl-loading-error" class="thm-loading">
|
||||||
|
An error occurred. <br /> Please refresh the page and try again.
|
||||||
|
<div id="rl-loading-error-additional"></div>
|
||||||
|
</div>
|
||||||
|
<div id="rl-content">
|
||||||
|
<div id="rl-popups"></div>
|
||||||
|
<div id="rl-center">
|
||||||
|
<div id="rl-top"></div>
|
||||||
|
<div id="rl-left"></div>
|
||||||
|
<div id="rl-right"></div>
|
||||||
|
<div id="rl-bottom"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="rl-templates"></div>
|
||||||
|
<div id="rl-hidden"></div>
|
||||||
|
|
@ -32,7 +32,7 @@ class RainLoopStorage
|
||||||
setHash() {
|
setHash() {
|
||||||
const
|
const
|
||||||
key = 'AuthAccountHash',
|
key = 'AuthAccountHash',
|
||||||
appData = window.rainloopAppData
|
appData = window.__rlah_data()
|
||||||
;
|
;
|
||||||
if (this.s)
|
if (this.s)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ class SettingsStorage
|
||||||
appSettings = {};
|
appSettings = {};
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.settings = window.rainloopAppData || {};
|
this.settings = window.__rlah_data() || {};
|
||||||
this.settings = Utils.isNormal(this.settings) ? this.settings : {};
|
this.settings = Utils.isNormal(this.settings) ? this.settings : {};
|
||||||
|
|
||||||
this.appSettings = this.settings.System || null;
|
this.appSettings = this.settings.System || null;
|
||||||
|
|
|
||||||
|
|
@ -349,7 +349,7 @@ html.rl-ctrl-key-pressed {
|
||||||
#rl-loading, #rl-loading-error {
|
#rl-loading, #rl-loading-error {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
font-size: 30px;
|
font-size: 30px;
|
||||||
line-height: 100%;
|
line-height: 130%;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 65px;
|
height: 65px;
|
||||||
|
|
@ -370,6 +370,14 @@ html.rl-ctrl-key-pressed {
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#rl-app{
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#rl-check{
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
html.rl-mobile .hide-on-mobile {
|
html.rl-mobile .hide-on-mobile {
|
||||||
display: none !important;
|
display: none !important;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -28,10 +28,6 @@
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#rl-check {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.opentip-container {
|
.opentip-container {
|
||||||
|
|
||||||
z-index: 2001 !important;
|
z-index: 2001 !important;
|
||||||
|
|
|
||||||
25
dev/boot.jsx
25
dev/boot.jsx
|
|
@ -1,12 +1,27 @@
|
||||||
|
|
||||||
import window from 'window';
|
import window from 'window';
|
||||||
|
import jsloader from 'Common/Loader';
|
||||||
|
import {progressJs} from 'progress.js/src/progress.js';
|
||||||
|
|
||||||
|
window.jsloader = jsloader;
|
||||||
|
window.progressJs = window.progressJs || progressJs();
|
||||||
|
|
||||||
|
window.progressJs.onbeforeend(() => {
|
||||||
|
if (window.$)
|
||||||
|
{
|
||||||
|
window.$('.progressjs-container').hide();
|
||||||
|
window.setTimeout(() => {
|
||||||
|
window.$('.progressjs-container').remove();
|
||||||
|
}, 100);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
require('json2/json2.js');
|
require('json2/json2.js');
|
||||||
require('modernizr/modernizr-custom.js');
|
require('modernizr/modernizr-custom.js');
|
||||||
|
|
||||||
require('Common/Booter.jsx');
|
require('Common/Booter.jsx');
|
||||||
|
|
||||||
import {$LAB} from 'labjs/LAB.src.js';
|
if (window.__runBoot)
|
||||||
import {progressJs} from 'progress.js/src/progress.js';
|
{
|
||||||
|
window.__runBoot();
|
||||||
window.$LAB = $LAB;
|
}
|
||||||
window.progressJs = progressJs;
|
|
||||||
|
|
|
||||||
|
|
@ -48,17 +48,10 @@ export default (App) => {
|
||||||
window['rl']['EmailModel'] = EmailModel;
|
window['rl']['EmailModel'] = EmailModel;
|
||||||
window['rl']['Enums'] = Enums;
|
window['rl']['Enums'] = Enums;
|
||||||
|
|
||||||
window['__APP_BOOT'] = function (fCall) {
|
window.__APP_BOOT = function (fCall) {
|
||||||
|
|
||||||
$(_.delay(function () {
|
$(_.delay(function () {
|
||||||
|
|
||||||
if (!$('#rl-check').is(':visible'))
|
|
||||||
{
|
|
||||||
Globals.$html.addClass('no-css');
|
|
||||||
}
|
|
||||||
|
|
||||||
$('#rl-check').remove();
|
|
||||||
|
|
||||||
if (window['rainloopTEMPLATES'] && window['rainloopTEMPLATES'][0])
|
if (window['rainloopTEMPLATES'] && window['rainloopTEMPLATES'][0])
|
||||||
{
|
{
|
||||||
$('#rl-templates').html(window['rainloopTEMPLATES'][0]);
|
$('#rl-templates').html(window['rainloopTEMPLATES'][0]);
|
||||||
|
|
@ -79,7 +72,7 @@ export default (App) => {
|
||||||
fCall(false);
|
fCall(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
window['__APP_BOOT'] = null;
|
window.__APP_BOOT = null;
|
||||||
|
|
||||||
}, 10));
|
}, 10));
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -97,7 +97,7 @@ function copyFile(sFile, sNewFile, callback)
|
||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg.paths.globjs = 'dev/**/*.{js,jsx}';
|
cfg.paths.globjs = 'dev/**/*.{js,jsx,html}';
|
||||||
cfg.paths.globjsonly = 'dev/**/*.js';
|
cfg.paths.globjsonly = 'dev/**/*.js';
|
||||||
cfg.paths.globjsxonly = 'dev/**/*.jsx';
|
cfg.paths.globjsxonly = 'dev/**/*.jsx';
|
||||||
cfg.paths.static = 'rainloop/v/' + cfg.devVersion + '/static/';
|
cfg.paths.static = 'rainloop/v/' + cfg.devVersion + '/static/';
|
||||||
|
|
@ -260,7 +260,6 @@ gulp.task('package:community-off', function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('css:clear-less', ['css:main-begin'], function() {
|
gulp.task('css:clear-less', ['css:main-begin'], function() {
|
||||||
|
|
||||||
return gulp.src(cfg.paths.staticCSS + cfg.paths.less.main.name, {read: false})
|
return gulp.src(cfg.paths.staticCSS + cfg.paths.less.main.name, {read: false})
|
||||||
.pipe(require('gulp-rimraf')());
|
.pipe(require('gulp-rimraf')());
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
"name": "RainLoop",
|
"name": "RainLoop",
|
||||||
"title": "RainLoop Webmail",
|
"title": "RainLoop Webmail",
|
||||||
"version": "1.10.0",
|
"version": "1.10.0",
|
||||||
"release": "108",
|
"release": "112",
|
||||||
"ownCloudPackageVersion": "4.16",
|
"ownCloudPackageVersion": "4.16",
|
||||||
"description": "Simple, modern & fast web-based email client",
|
"description": "Simple, modern & fast web-based email client",
|
||||||
"homepage": "http://rainloop.net",
|
"homepage": "http://rainloop.net",
|
||||||
|
|
@ -84,6 +84,7 @@
|
||||||
"lodash": "~3.9.3",
|
"lodash": "~3.9.3",
|
||||||
"node-fs": "*",
|
"node-fs": "*",
|
||||||
"node-notifier": "~4.2.3",
|
"node-notifier": "~4.2.3",
|
||||||
|
"raw-loader": "^0.5.1",
|
||||||
"rimraf": "*",
|
"rimraf": "*",
|
||||||
"webpack": "*"
|
"webpack": "*"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
8
phpunit.xml
Normal file
8
phpunit.xml
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<phpunit colors="true" stopOnFailure="true" syntaxCheck="true" bootstrap="tests/bootstrap.php">
|
||||||
|
<testsuites>
|
||||||
|
<testsuite name="RainLoop Test Suite">
|
||||||
|
<directory>tests</directory>
|
||||||
|
</testsuite>
|
||||||
|
</testsuites>
|
||||||
|
</phpunit>
|
||||||
|
|
@ -1905,11 +1905,6 @@ NewThemeLink IncludeCss LoadingDescriptionEsc TemplatesLink LangLink IncludeBack
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$sStaticCache = \md5(APP_VERSION.$this->Plugins()->Hash());
|
|
||||||
|
|
||||||
$sTheme = $this->ValidateTheme($sTheme, $bMobile);
|
|
||||||
$sNewThemeLink = './?/Css/0/'.($bAdmin ? 'Admin' : 'User').'/-/'.$sTheme.'/-/'.$sStaticCache.'/Hash/-/';
|
|
||||||
|
|
||||||
if (!$aResult['Auth'])
|
if (!$aResult['Auth'])
|
||||||
{
|
{
|
||||||
if (!$bAdmin)
|
if (!$bAdmin)
|
||||||
|
|
@ -1923,14 +1918,11 @@ NewThemeLink IncludeCss LoadingDescriptionEsc TemplatesLink LangLink IncludeBack
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$sPluginsLink = '';
|
$sTheme = $this->ValidateTheme($sTheme, $bMobile);
|
||||||
if (0 < $this->Plugins()->Count() && $this->Plugins()->HaveJs($bAdmin))
|
$sStaticCache = $this->StaticCache();
|
||||||
{
|
|
||||||
$sPluginsLink = './?/Plugins/0/'.($bAdmin ? 'Admin' : 'User').'/'.$sStaticCache.'/';
|
|
||||||
}
|
|
||||||
|
|
||||||
$aResult['Theme'] = $sTheme;
|
$aResult['Theme'] = $sTheme;
|
||||||
$aResult['NewThemeLink'] = $sNewThemeLink;
|
$aResult['NewThemeLink'] = $this->ThemeLink($sTheme, $bAdmin);
|
||||||
|
|
||||||
$aResult['Language'] = $this->ValidateLanguage($sLanguage, '', false);
|
$aResult['Language'] = $this->ValidateLanguage($sLanguage, '', false);
|
||||||
$aResult['LanguageAdmin'] = $this->ValidateLanguage($sLanguageAdmin, '', true);
|
$aResult['LanguageAdmin'] = $this->ValidateLanguage($sLanguageAdmin, '', true);
|
||||||
|
|
@ -1940,11 +1932,23 @@ NewThemeLink IncludeCss LoadingDescriptionEsc TemplatesLink LangLink IncludeBack
|
||||||
$aResult['UserLanguage'] = $this->ValidateLanguage($aResult['UserLanguageRaw'], '', false, true);
|
$aResult['UserLanguage'] = $this->ValidateLanguage($aResult['UserLanguageRaw'], '', false, true);
|
||||||
$aResult['UserLanguageAdmin'] = $this->ValidateLanguage($aResult['UserLanguageRaw'], '', true, true);
|
$aResult['UserLanguageAdmin'] = $this->ValidateLanguage($aResult['UserLanguageRaw'], '', true, true);
|
||||||
|
|
||||||
|
$aResult['PluginsLink'] = '';
|
||||||
|
if (0 < $this->Plugins()->Count() && $this->Plugins()->HaveJs($bAdmin))
|
||||||
|
{
|
||||||
|
$aResult['PluginsLink'] = './?/Plugins/0/'.($bAdmin ? 'Admin' : 'User').'/'.$sStaticCache.'/';
|
||||||
|
}
|
||||||
|
|
||||||
$aResult['LangLink'] = './?/Lang/0/'.($bAdmin ? 'Admin' : 'App').'/'.
|
$aResult['LangLink'] = './?/Lang/0/'.($bAdmin ? 'Admin' : 'App').'/'.
|
||||||
($bAdmin ? $aResult['LanguageAdmin'] : $aResult['Language']).'/'.$sStaticCache.'/';
|
($bAdmin ? $aResult['LanguageAdmin'] : $aResult['Language']).'/'.$sStaticCache.'/';
|
||||||
|
|
||||||
$aResult['TemplatesLink'] = './?/Templates/0/'.($bAdmin ? 'Admin' : 'App').'/'.$sStaticCache.'/';
|
$aResult['TemplatesLink'] = './?/Templates/0/'.($bAdmin ? 'Admin' : 'App').'/'.$sStaticCache.'/';
|
||||||
$aResult['PluginsLink'] = $sPluginsLink;
|
|
||||||
|
$bAppJsDebug = !!$this->Config()->Get('labs', 'use_app_debug_js', false);
|
||||||
|
|
||||||
|
$aResult['StaticLibJsLink'] = $this->StaticPath('js/min/libs.js');
|
||||||
|
$aResult['StaticAppJsLink'] = $this->StaticPath('js/'.($bAppJsDebug ? '' : 'min/').($bAdmin ? 'admin' : 'app').'.js');
|
||||||
|
$aResult['StaticEditorJsLink'] = $this->StaticPath('ckeditor/ckeditor.js');
|
||||||
|
|
||||||
$aResult['EditorDefaultType'] = \in_array($aResult['EditorDefaultType'], array('Plain', 'Html', 'HtmlForced', 'PlainForced')) ?
|
$aResult['EditorDefaultType'] = \in_array($aResult['EditorDefaultType'], array('Plain', 'Html', 'HtmlForced', 'PlainForced')) ?
|
||||||
$aResult['EditorDefaultType'] : 'Plain';
|
$aResult['EditorDefaultType'] : 'Plain';
|
||||||
|
|
||||||
|
|
@ -9057,6 +9061,29 @@ NewThemeLink IncludeCss LoadingDescriptionEsc TemplatesLink LangLink IncludeBack
|
||||||
return $mResult;
|
return $mResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function StaticCache()
|
||||||
|
{
|
||||||
|
static $sCache = null;
|
||||||
|
if (!$sCache)
|
||||||
|
{
|
||||||
|
$sCache = \md5(APP_VERSION.$this->Plugins()->Hash());
|
||||||
|
}
|
||||||
|
return $sCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $sTheme
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function ThemeLink($sTheme, $bAdmin)
|
||||||
|
{
|
||||||
|
return './?/Css/0/'.($bAdmin ? 'Admin' : 'User').'/-/'.$sTheme.'/-/'.$this->StaticCache().'/Hash/-/';
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string $sTheme
|
* @param string $sTheme
|
||||||
*
|
*
|
||||||
|
|
@ -9694,6 +9721,18 @@ NewThemeLink IncludeCss LoadingDescriptionEsc TemplatesLink LangLink IncludeBack
|
||||||
return isset($aLang[$sKey]) ? $aLang[$sKey] : $sKey;
|
return isset($aLang[$sKey]) ? $aLang[$sKey] : $sKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $sPath
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function StaticPath($sPath)
|
||||||
|
{
|
||||||
|
$sResult = \RainLoop\Utils::WebStaticPath().$sPath;
|
||||||
|
return $sResult.(false === \strpos($sResult, '?') ? '?' : '&').
|
||||||
|
($this->IsOpen() ? 'community' : 'standard');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return MailSo\Cache\CacheClient|null
|
* @return MailSo\Cache\CacheClient|null
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -241,7 +241,7 @@ class Service
|
||||||
$sResult .= '][owncloud:true';
|
$sResult .= '][owncloud:true';
|
||||||
}
|
}
|
||||||
|
|
||||||
$sResult .= '] //-->';
|
$sResult .= ']-->';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Output result
|
// Output result
|
||||||
|
|
@ -259,9 +259,7 @@ class Service
|
||||||
*/
|
*/
|
||||||
private function staticPath($sPath)
|
private function staticPath($sPath)
|
||||||
{
|
{
|
||||||
$sResult = \RainLoop\Utils::WebStaticPath().$sPath;
|
return $this->oActions->StaticPath($sPath);
|
||||||
return $sResult.(false === \strpos($sResult, '?') ? '?' : '&').
|
|
||||||
($this->oActions->IsOpen() ? 'v=community' : 'v=standard');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -283,42 +281,27 @@ class Service
|
||||||
|
|
||||||
$sFaviconUrl = (string) $this->oActions->Config()->Get('webmail', 'favicon_url', '');
|
$sFaviconUrl = (string) $this->oActions->Config()->Get('webmail', 'favicon_url', '');
|
||||||
|
|
||||||
$aData = array(
|
$sFaviconPngLink = $sFaviconUrl ? $sFaviconUrl : $this->staticPath('apple-touch-icon.png');
|
||||||
'Language' => $sLanguage,
|
$sAppleTouchLink = $sFaviconUrl ? '' : $this->staticPath('apple-touch-icon.png');
|
||||||
'Theme' => $sTheme,
|
|
||||||
'FaviconPngLink' => $sFaviconUrl ? $sFaviconUrl : $this->staticPath('apple-touch-icon.png'),
|
|
||||||
'AppleTouchLink' => $sFaviconUrl ? '' : $this->staticPath('apple-touch-icon.png'),
|
|
||||||
'AppCssLink' => $this->staticPath('css/app'.($bAppCssDebug ? '' : '.min').'.css'),
|
|
||||||
'BootJsLink' => $this->staticPath('js/'.($bAppJsDebug ? '' : 'min/').'boot.js'),
|
|
||||||
'LibJsLink' => $this->staticPath('js/min/libs.js'),
|
|
||||||
'EditorJsLink' => $this->staticPath('ckeditor/ckeditor.js'),
|
|
||||||
'OpenPgpJsLink' => $this->staticPath('js/min/openpgp.min.js'),
|
|
||||||
'AppJsCommonLink' => $this->staticPath('js/'.($bAppJsDebug ? '' : 'min/').'common.js'),
|
|
||||||
'AppJsLink' => $this->staticPath('js/'.($bAppJsDebug ? '' : 'min/').($bAdmin ? 'admin' : 'app').'.js')
|
|
||||||
);
|
|
||||||
|
|
||||||
$aAdd = array();
|
|
||||||
$aAdd[] = $bMobile ? 'mobile' : 'no-mobile';
|
|
||||||
$aAdd[] = $bMobileDevice ? '1' : '0';
|
|
||||||
|
|
||||||
$aTemplateParameters = array(
|
$aTemplateParameters = array(
|
||||||
'{{BaseAppDataScriptLink}}' => ($bAdmin ? './?/AdminAppData' : './?/AppData').(0 < \count($aAdd) ? '@'.\implode('-', $aAdd) : '').'/',
|
'{{BaseAppFaviconPngLinkTag}}' => $sFaviconPngLink ? '<link type="image/png" rel="shortcut icon" href="'.$sFaviconPngLink.'" />' : '',
|
||||||
'{{BaseAppFaviconPngLinkTag}}' => $aData['FaviconPngLink'] ? '<link rel="shortcut icon" href="'.$aData['FaviconPngLink'].'" type="image/png" />' : '',
|
'{{BaseAppFaviconTouchLinkTag}}' => $sAppleTouchLink ? '<link type="image/png" rel="apple-touch-icon" href="'.$sAppleTouchLink.'" />' : '',
|
||||||
'{{BaseAppFaviconTouchLinkTag}}' => $aData['AppleTouchLink'] ? '<link rel="apple-touch-icon" href="'.$aData['AppleTouchLink'].'" type="image/png" />' : '',
|
'{{BaseAppMainCssLink}}' => $this->staticPath('css/app'.($bAppCssDebug ? '' : '.min').'.css'),
|
||||||
'{{BaseAppAppleTouchFile}}' => $aData['AppleTouchLink'],
|
'{{BaseAppThemeCssLink}}' => $this->oActions->ThemeLink($sTheme, $bAdmin),
|
||||||
'{{BaseAppMainCssLink}}' => $aData['AppCssLink'],
|
'{{BaseAppBootScriptLink}}' => $this->staticPath('js/'.($bAppJsDebug ? '' : 'min/').'boot.js'),
|
||||||
'{{BaseAppBootScriptLink}}' => $aData['BootJsLink'],
|
|
||||||
'{{BaseAppLibsScriptLink}}' => $aData['LibJsLink'],
|
|
||||||
'{{BaseAppEditorScriptLink}}' => $aData['EditorJsLink'],
|
|
||||||
'{{BaseAppOpenPgpScriptLink}}' => $aData['OpenPgpJsLink'],
|
|
||||||
'{{BaseAppMainCommonScriptLink}}' => $aData['AppJsCommonLink'],
|
|
||||||
'{{BaseAppMainScriptLink}}' => $aData['AppJsLink'],
|
|
||||||
'{{BaseVersion}}' => APP_VERSION,
|
|
||||||
'{{BaseViewport}}' => $bMobile ? 'width=device-width,initial-scale=1,user-scalable=no' : 'width=950,maximum-scale=2',
|
'{{BaseViewport}}' => $bMobile ? 'width=device-width,initial-scale=1,user-scalable=no' : 'width=950,maximum-scale=2',
|
||||||
'{{BaseDir}}' => 'ltr'
|
'{{BaseDir}}' => false && \in_array($sLanguage, array('ar', 'he', 'ur')) ? 'rtl' : 'ltr'
|
||||||
// '{{BaseDir}}' => \in_array($aData['Language'], array('ar', 'he', 'ur')) ? 'rtl' : 'ltr'
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$aTemplateParameters['{{RainloopBootData}}'] = \json_encode(array(
|
||||||
|
'admin' => $bAdmin,
|
||||||
|
'language' => $sLanguage,
|
||||||
|
'theme' => $sTheme,
|
||||||
|
'mobile' => $bMobile,
|
||||||
|
'mobileDevice' => $bMobileDevice
|
||||||
|
));
|
||||||
|
|
||||||
$aTemplateParameters['{{BaseHash}}'] = \md5(
|
$aTemplateParameters['{{BaseHash}}'] = \md5(
|
||||||
\implode('~', array(
|
\implode('~', array(
|
||||||
$bAdmin ? '1' : '0',
|
$bAdmin ? '1' : '0',
|
||||||
|
|
|
||||||
|
|
@ -1369,9 +1369,8 @@ class ServiceActions
|
||||||
private function compileAppData($aAppData, $bWrapByScriptTag = true)
|
private function compileAppData($aAppData, $bWrapByScriptTag = true)
|
||||||
{
|
{
|
||||||
return
|
return
|
||||||
($bWrapByScriptTag ? '<script data-cfasync="false">' : '').
|
($bWrapByScriptTag ? '<script type="text/javascript" data-cfasync="false">' : '').
|
||||||
'window.rainloopAppData='.\json_encode($aAppData).';'.
|
'if(window.__initAppData){window.__initAppData('.\json_encode($aAppData).');}'.
|
||||||
'if(window.__rlah_set){__rlah_set()};'.
|
|
||||||
($bWrapByScriptTag ? '</script>' : '')
|
($bWrapByScriptTag ? '</script>' : '')
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -475,12 +475,13 @@ class Utils
|
||||||
public static function ClearHtmlOutput($sHtml)
|
public static function ClearHtmlOutput($sHtml)
|
||||||
{
|
{
|
||||||
// return $sHtml;
|
// return $sHtml;
|
||||||
return \str_replace('> <', '><',
|
return \trim(\str_replace('> <', '><',
|
||||||
|
\str_replace('" />', '"/>',
|
||||||
\preg_replace('/[\s]+ /i', ' ',
|
\preg_replace('/[\s]+ /i', ' ',
|
||||||
\preg_replace('/ [\s]+/i', ' ',
|
\preg_replace('/ [\s]+/i', ' ',
|
||||||
\preg_replace('/[\r\n\t]+/', ' ',
|
\preg_replace('/[\r\n\t]+/', ' ',
|
||||||
$sHtml
|
$sHtml
|
||||||
))));
|
))))));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -1,74 +1,29 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html class="no-js rl-booted-trigger rl-started-trigger" dir="{{BaseDir}}">
|
<html class="no-js rl-booted-trigger rl-started-trigger" dir="{{BaseDir}}">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
|
|
||||||
<meta id="rl-head-viewport" name="viewport" content="{{BaseViewport}}">
|
|
||||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
|
||||||
<noscript>
|
<noscript>
|
||||||
<meta http-equiv="refresh" content="0; URL=./?/NoScript" />
|
<meta http-equiv="refresh" content="0; URL=./?/NoScript" />
|
||||||
</noscript>
|
</noscript>
|
||||||
<!--[if lte IE 8]>
|
<!--[if lte IE 8]>
|
||||||
<meta http-equiv="refresh" content="0; URL=./?/BadBrowser" />
|
<meta http-equiv="refresh" content="0; URL=./?/BadBrowser" />
|
||||||
<![endif]-->
|
<![endif]-->
|
||||||
<script type="text/javascript" data-cfasync="false">
|
<meta charset="utf-8" />
|
||||||
if (!window.navigator || !window.navigator.cookieEnabled) {
|
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
|
||||||
window.document.location.replace('./?/NoCookie');
|
<meta name="viewport" content="{{BaseViewport}}" id="app-head-viewport">
|
||||||
}
|
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||||
</script>
|
|
||||||
<meta name="Author" content="RainLoop Team" />
|
|
||||||
<meta name="robots" content="noindex,nofollow,noodp" />
|
|
||||||
<meta name="google" content="notranslate" />
|
<meta name="google" content="notranslate" />
|
||||||
|
<meta name="robots" content="noindex,nofollow,noodp" />
|
||||||
|
<meta name="AppBootData" content='{{RainloopBootData}}' id="app-boot-data" />
|
||||||
<title></title>
|
<title></title>
|
||||||
<style>#rl-content{display:none;}#rl-check{display:none;}</style>
|
{{BaseAppFaviconPngLinkTag}}
|
||||||
{{BaseAppFaviconPngLinkTag}}{{BaseAppFaviconTouchLinkTag}}
|
{{BaseAppFaviconTouchLinkTag}}
|
||||||
|
<style>#rl-check{display:none}</style>
|
||||||
<link type="text/css" rel="stylesheet" href="{{BaseAppMainCssLink}}" />
|
<link type="text/css" rel="stylesheet" href="{{BaseAppMainCssLink}}" />
|
||||||
<link type="text/css" rel="stylesheet" id="rlThemeLink" />
|
<link type="text/css" rel="stylesheet" href="{{BaseAppThemeCssLink}}" id="app-theme-link" />
|
||||||
<script type="text/javascript" data-cfasync="false" src="{{BaseAppBootScriptLink}}"></script>
|
|
||||||
<script type="text/javascript" data-cfasync="false">
|
|
||||||
window.__includeAppScr('{{BaseAppDataScriptLink}}');
|
|
||||||
</script>
|
|
||||||
<script type="text/javascript" data-cfasync="false">
|
|
||||||
if (window.rainloopAppData && window.rainloopAppData['NewThemeLink']) {
|
|
||||||
window.document.getElementById('rlThemeLink').href = window.rainloopAppData['NewThemeLink'];
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<script type="text/javascript" data-cfasync="false">
|
|
||||||
if (window.rainloopAppData && window.rainloopAppData['IncludeCss']) {
|
|
||||||
window.__includeStyle(window.rainloopAppData['IncludeCss']);
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<script type="text/javascript" data-cfasync="false"></script>
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
<div id="rl-app"></div>
|
||||||
<div id="rl-check"></div>
|
<div id="rl-check"></div>
|
||||||
<div id="rl-bg" class="thm-body"></div>
|
<script type="text/javascript" data-cfasync="false" src="{{BaseAppBootScriptLink}}"></script>
|
||||||
<div id="rl-loading" class="thm-loading">
|
|
||||||
<div id="rl-loading-desc">Loading</div>
|
|
||||||
<div class="e-spinner">
|
|
||||||
<div class="e-bounce bounce1"></div>
|
|
||||||
<div class="e-bounce bounce2"></div>
|
|
||||||
<div class="e-bounce bounce3"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div id="rl-loading-error" class="thm-loading">
|
|
||||||
An Error occurred,
|
|
||||||
<br />
|
|
||||||
please refresh the page and try again.
|
|
||||||
<div id="rl-loading-error-additional"></div>
|
|
||||||
</div>
|
|
||||||
<div id="rl-content">
|
|
||||||
<div id="rl-popups"></div>
|
|
||||||
<div id="rl-center">
|
|
||||||
<div id="rl-top"></div>
|
|
||||||
<div id="rl-left"></div>
|
|
||||||
<div id="rl-right"></div>
|
|
||||||
<div id="rl-bottom"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div id="rl-templates"></div>
|
|
||||||
<div id="rl-hidden"></div>
|
|
||||||
<script type="text/javascript" data-cfasync="false">__showDescription(window.rainloopAppData ? window.rainloopAppData['LoadingDescriptionEsc'] : '');</script>
|
|
||||||
<script type="text/javascript" data-cfasync="false">__runApp('{{BaseAppLibsScriptLink}}', '{{BaseAppMainScriptLink}}', '{{BaseAppEditorScriptLink}}');</script>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -187,9 +187,39 @@
|
||||||
.thm-rgba-background-color(@message-background-color, @message-rgba-background-color);
|
.thm-rgba-background-color(@message-background-color, @message-rgba-background-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#rl-app{
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
html.no-css {
|
html.no-css {
|
||||||
|
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
font-family: Arial, Verdana, Geneva, sans-serif;
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#rl-loading, #rl-loading-error {
|
||||||
|
position: absolute;
|
||||||
|
font-size: 30px;
|
||||||
|
line-height: 130%;
|
||||||
|
top: 50%;
|
||||||
|
width: 100%;
|
||||||
|
height: 65px;
|
||||||
|
margin: 0;
|
||||||
|
margin-top: -60px;
|
||||||
|
background-color: transparent;
|
||||||
|
text-align: center;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progressjs-container {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
.thm-body {
|
.thm-body {
|
||||||
color: #333;
|
color: #333;
|
||||||
background-color: #aaa;
|
background-color: #aaa;
|
||||||
|
|
|
||||||
|
|
@ -3,13 +3,12 @@
|
||||||
<div class="btn-toolbar">
|
<div class="btn-toolbar">
|
||||||
<div class="btn-group btn-group-last pull-right dropdown colored-toggle" data-bind="registrateBootstrapDropdown: true, openDropdownTrigger: accountMenuDropdownTrigger">
|
<div class="btn-group btn-group-last pull-right dropdown colored-toggle" data-bind="registrateBootstrapDropdown: true, openDropdownTrigger: accountMenuDropdownTrigger">
|
||||||
<a id="top-system-dropdown-id" href="#" tabindex="-1" class="btn single btn-ellipsis btn-block dropdown-toggle system-dropdown" data-toggle="dropdown">
|
<a id="top-system-dropdown-id" href="#" tabindex="-1" class="btn single btn-ellipsis btn-block dropdown-toggle system-dropdown" data-toggle="dropdown">
|
||||||
<i data-bind="css: {'icon-user': !accounts.loading(), 'icon-spinner animated': accounts.loading()}"
|
<i data-bind="css: {'icon-user': !accounts.loading(), 'icon-spinner animated': accounts.loading()}"></i>
|
||||||
></i>
|
|
||||||
<!--
|
<!--
|
||||||
<b data-bind="text: accountsUnreadCount, visible: 100 > accountsUnreadCount() && 0 < accountsUnreadCount()"></b>
|
<b data-bind="text: accountsUnreadCount, visible: 100 > accountsUnreadCount() && 0 < accountsUnreadCount()"></b>
|
||||||
<b data-bind="visible: 99 < accountsUnreadCount()">99+</b>
|
<b data-bind="visible: 99 < accountsUnreadCount()">99+</b>
|
||||||
-->
|
|
||||||
|
|
||||||
|
-->
|
||||||
|
|
||||||
<span class="caret"></span>
|
<span class="caret"></span>
|
||||||
</a>
|
</a>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
url: 'https://mail.rainloop.net/',
|
|
||||||
testLogin: 'demo@rainloop.test',
|
|
||||||
testPassword: '12345'
|
|
||||||
};
|
|
||||||
1
tests/bootstrap.php
Normal file
1
tests/bootstrap.php
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
<?php
|
||||||
|
|
@ -1,70 +0,0 @@
|
||||||
|
|
||||||
var cfg = require('./_config.js');
|
|
||||||
|
|
||||||
casper.start(cfg.url);
|
|
||||||
|
|
||||||
casper.then(function() {
|
|
||||||
this.echo('testing: ' + cfg.url);
|
|
||||||
}).wait(100);
|
|
||||||
|
|
||||||
casper.then(function() {
|
|
||||||
|
|
||||||
casper.test.begin('Login page should contains "Sign In" button', 1, function (test) {
|
|
||||||
|
|
||||||
casper.then(function() {
|
|
||||||
test.assertExists('button.buttonLogin');
|
|
||||||
});
|
|
||||||
|
|
||||||
casper.then(function() {
|
|
||||||
test.done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
casper.test.begin('Login page should allow langs selection', 3, function (test) {
|
|
||||||
|
|
||||||
casper.then(function() {
|
|
||||||
test.assertExists('.e-languages .flag-selector .flag-name');
|
|
||||||
});
|
|
||||||
|
|
||||||
casper.then(function() {
|
|
||||||
this.click('.e-languages .flag-selector .flag-name');
|
|
||||||
}).wait(300);
|
|
||||||
|
|
||||||
casper.then(function() {
|
|
||||||
test.assertExists('.b-languages-content');
|
|
||||||
});
|
|
||||||
|
|
||||||
casper.then(function() {
|
|
||||||
this.click('.b-languages-content .lang-item .flag.flag-ru_ru');
|
|
||||||
}).wait(1000);
|
|
||||||
|
|
||||||
casper.then(function() {
|
|
||||||
test.assertEquals('Войти', this.fetchText('button.buttonLogin'));
|
|
||||||
});
|
|
||||||
|
|
||||||
casper.then(function() {
|
|
||||||
test.done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
casper.test.begin('Login page submit', 1, function (test) {
|
|
||||||
|
|
||||||
casper.then(function() {
|
|
||||||
this.fill('form.loginForm', {
|
|
||||||
'RainLoopEmail': cfg.testLogin,
|
|
||||||
'RainLoopPassword': cfg.testPassword
|
|
||||||
}, true);
|
|
||||||
}).wait(3000);
|
|
||||||
|
|
||||||
casper.then(function() {
|
|
||||||
test.assertEquals(cfg.testLogin, this.fetchText('.accountPlace'));
|
|
||||||
});
|
|
||||||
|
|
||||||
casper.then(function() {
|
|
||||||
test.done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
casper.run();
|
|
||||||
2
vendors/es6-promise-polyfill/.gitignore
vendored
Normal file
2
vendors/es6-promise-polyfill/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
/node_modules
|
||||||
|
/tmp
|
||||||
3
vendors/es6-promise-polyfill/.npmignore
vendored
Normal file
3
vendors/es6-promise-polyfill/.npmignore
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
/node_modules/
|
||||||
|
/tmp
|
||||||
|
/test
|
||||||
6
vendors/es6-promise-polyfill/.travis.yml
vendored
Normal file
6
vendors/es6-promise-polyfill/.travis.yml
vendored
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
language: node_js
|
||||||
|
sudo: false
|
||||||
|
node_js:
|
||||||
|
- "0.12"
|
||||||
|
- "node"
|
||||||
|
- "iojs"
|
||||||
18
vendors/es6-promise-polyfill/CHANGELOG.md
vendored
Normal file
18
vendors/es6-promise-polyfill/CHANGELOG.md
vendored
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
## 1.2.0 (December 8, 2015)
|
||||||
|
|
||||||
|
- Support for IE8 and below
|
||||||
|
- Promises/A+ tests added
|
||||||
|
|
||||||
|
## 1.1.0 (October 16, 2015)
|
||||||
|
|
||||||
|
- Change way to get reference to `global`, since `Function()()` may be prohibited
|
||||||
|
- Add AMD support
|
||||||
|
|
||||||
|
## 1.0.1 (September 14, 2015)
|
||||||
|
|
||||||
|
- Fix exports - use polyfill only if native implementation isn't supported
|
||||||
|
- Add license
|
||||||
|
|
||||||
|
## 1.0.0 (June 19, 2014)
|
||||||
|
|
||||||
|
- Init release
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
Copyright 2015 RainLoop Team
|
(The MIT License)
|
||||||
|
|
||||||
|
Copyright (c) 2014 Roman Dvornov
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
a copy of this software and associated documentation files (the
|
a copy of this software and associated documentation files (the
|
||||||
88
vendors/es6-promise-polyfill/README.md
vendored
Normal file
88
vendors/es6-promise-polyfill/README.md
vendored
Normal file
|
|
@ -0,0 +1,88 @@
|
||||||
|
[](https://www.npmjs.com/package/es6-promise-polyfill)
|
||||||
|
[](https://travis-ci.org/lahmatiy/es6-promise-polyfill)
|
||||||
|
|
||||||
|
# ES6 Promise polyfill
|
||||||
|
|
||||||
|
This is a polyfill of [ES6 Promise](https://github.com/domenic/promises-unwrapping). The implementation based on [Jake Archibald implementation](https://github.com/jakearchibald/es6-promise) a subset of [rsvp.js](https://github.com/tildeio/rsvp.js). If you're wanting extra features and more debugging options, check out the [full library](https://github.com/tildeio/rsvp.js).
|
||||||
|
|
||||||
|
For API details and how to use promises, see the <a href="http://www.html5rocks.com/en/tutorials/es6/promises/">JavaScript Promises HTML5Rocks article</a>.
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
The main target: implementation should be conformance with browser's implementations and to be minimal as possible in size. So it's strictly polyfill of ES6 Promise specification and nothing more.
|
||||||
|
|
||||||
|
It passes both [Promises/A+ test suite](https://github.com/promises-aplus/promises-tests) and [rsvp.js test suite](https://github.com/jakearchibald/es6-promise/tree/master/test). And as small as 2,6KB min (or 1KB min+gzip).
|
||||||
|
|
||||||
|
The polyfill uses `setImmediate` if available, or fallback to use `setTimeout`. Use [setImmediate polyfill](https://github.com/YuzuJS/setImmediate) by @YuzuJS to reach better performance.
|
||||||
|
|
||||||
|
## How to use
|
||||||
|
|
||||||
|
### Browser
|
||||||
|
|
||||||
|
To install:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
bower install es6-promise-polyfill
|
||||||
|
```
|
||||||
|
|
||||||
|
To use:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<script src="bower_components/es6-promise-polyfill/promise.min.js"></script>
|
||||||
|
<script>
|
||||||
|
var promise = new Promise(...);
|
||||||
|
</script>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Node.js
|
||||||
|
|
||||||
|
To install:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm install es6-promise-polyfill
|
||||||
|
```
|
||||||
|
|
||||||
|
To use:
|
||||||
|
|
||||||
|
```js
|
||||||
|
var Promise = require('es6-promise-polyfill').Promise;
|
||||||
|
var promise = new Promise(...);
|
||||||
|
```
|
||||||
|
|
||||||
|
### AMD
|
||||||
|
|
||||||
|
To install:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm install es6-promise-polyfill
|
||||||
|
```
|
||||||
|
|
||||||
|
To use:
|
||||||
|
|
||||||
|
```js
|
||||||
|
define(['es6-promise-polyfill'], function(Promise) {
|
||||||
|
var promise = new Promise(...);
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage in IE<9
|
||||||
|
|
||||||
|
`catch` is a reserved word in IE<9, meaning `promise.catch(func)` throws a syntax error. To work around this, use a string to access the property:
|
||||||
|
|
||||||
|
```js
|
||||||
|
promise['catch'](function(err) {
|
||||||
|
// ...
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
Or use `.then` instead:
|
||||||
|
|
||||||
|
```js
|
||||||
|
promise.then(undefined, function(err) {
|
||||||
|
// ...
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
Licensed under the MIT License.
|
||||||
11
vendors/es6-promise-polyfill/bower.json
vendored
Normal file
11
vendors/es6-promise-polyfill/bower.json
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
{
|
||||||
|
"name": "es6-promise-polyfill",
|
||||||
|
"version": "1.1.1",
|
||||||
|
"main": "promise.js",
|
||||||
|
"ignore": [
|
||||||
|
".*",
|
||||||
|
"**/.*",
|
||||||
|
"node_modules",
|
||||||
|
"test"
|
||||||
|
]
|
||||||
|
}
|
||||||
27
vendors/es6-promise-polyfill/package.json
vendored
Normal file
27
vendors/es6-promise-polyfill/package.json
vendored
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
{
|
||||||
|
"name": "es6-promise-polyfill",
|
||||||
|
"description": "Polyfill for ES6 Promise",
|
||||||
|
"version": "1.2.0",
|
||||||
|
"author": "Roman Dvornov <rdvornov@gmail.com>",
|
||||||
|
"license": "MIT",
|
||||||
|
"repository": "lahmatiy/es6-promise-polyfill",
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/lahmatiy/es6-promise-polyfill/issues"
|
||||||
|
},
|
||||||
|
"main": "promise.js",
|
||||||
|
"dependencies": {
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"promises-aplus-tests": "*"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"test": "promises-aplus-tests test/test-adapter"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"es6",
|
||||||
|
"es2015",
|
||||||
|
"polyfill",
|
||||||
|
"promise",
|
||||||
|
"promises"
|
||||||
|
]
|
||||||
|
}
|
||||||
346
vendors/es6-promise-polyfill/promise.js
vendored
Normal file
346
vendors/es6-promise-polyfill/promise.js
vendored
Normal file
|
|
@ -0,0 +1,346 @@
|
||||||
|
(function(global){
|
||||||
|
|
||||||
|
//
|
||||||
|
// Check for native Promise and it has correct interface
|
||||||
|
//
|
||||||
|
|
||||||
|
var NativePromise = global['Promise'];
|
||||||
|
var nativePromiseSupported =
|
||||||
|
NativePromise &&
|
||||||
|
// Some of these methods are missing from
|
||||||
|
// Firefox/Chrome experimental implementations
|
||||||
|
'resolve' in NativePromise &&
|
||||||
|
'reject' in NativePromise &&
|
||||||
|
'all' in NativePromise &&
|
||||||
|
'race' in NativePromise &&
|
||||||
|
// Older version of the spec had a resolver object
|
||||||
|
// as the arg rather than a function
|
||||||
|
(function(){
|
||||||
|
var resolve;
|
||||||
|
new NativePromise(function(r){ resolve = r; });
|
||||||
|
return typeof resolve === 'function';
|
||||||
|
})();
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// export if necessary
|
||||||
|
//
|
||||||
|
|
||||||
|
if (typeof exports !== 'undefined' && exports)
|
||||||
|
{
|
||||||
|
// node.js
|
||||||
|
exports.Promise = nativePromiseSupported ? NativePromise : Promise;
|
||||||
|
exports.Polyfill = Promise;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// AMD
|
||||||
|
if (typeof define == 'function' && define.amd)
|
||||||
|
{
|
||||||
|
define(function(){
|
||||||
|
return nativePromiseSupported ? NativePromise : Promise;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// in browser add to global
|
||||||
|
if (!nativePromiseSupported)
|
||||||
|
global['Promise'] = Promise;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Polyfill
|
||||||
|
//
|
||||||
|
|
||||||
|
var PENDING = 'pending';
|
||||||
|
var SEALED = 'sealed';
|
||||||
|
var FULFILLED = 'fulfilled';
|
||||||
|
var REJECTED = 'rejected';
|
||||||
|
var NOOP = function(){};
|
||||||
|
|
||||||
|
function isArray(value) {
|
||||||
|
return Object.prototype.toString.call(value) === '[object Array]';
|
||||||
|
}
|
||||||
|
|
||||||
|
// async calls
|
||||||
|
var asyncSetTimer = typeof setImmediate !== 'undefined' ? setImmediate : setTimeout;
|
||||||
|
var asyncQueue = [];
|
||||||
|
var asyncTimer;
|
||||||
|
|
||||||
|
function asyncFlush(){
|
||||||
|
// run promise callbacks
|
||||||
|
for (var i = 0; i < asyncQueue.length; i++)
|
||||||
|
asyncQueue[i][0](asyncQueue[i][1]);
|
||||||
|
|
||||||
|
// reset async asyncQueue
|
||||||
|
asyncQueue = [];
|
||||||
|
asyncTimer = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function asyncCall(callback, arg){
|
||||||
|
asyncQueue.push([callback, arg]);
|
||||||
|
|
||||||
|
if (!asyncTimer)
|
||||||
|
{
|
||||||
|
asyncTimer = true;
|
||||||
|
asyncSetTimer(asyncFlush, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function invokeResolver(resolver, promise) {
|
||||||
|
function resolvePromise(value) {
|
||||||
|
resolve(promise, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
function rejectPromise(reason) {
|
||||||
|
reject(promise, reason);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
resolver(resolvePromise, rejectPromise);
|
||||||
|
} catch(e) {
|
||||||
|
rejectPromise(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function invokeCallback(subscriber){
|
||||||
|
var owner = subscriber.owner;
|
||||||
|
var settled = owner.state_;
|
||||||
|
var value = owner.data_;
|
||||||
|
var callback = subscriber[settled];
|
||||||
|
var promise = subscriber.then;
|
||||||
|
|
||||||
|
if (typeof callback === 'function')
|
||||||
|
{
|
||||||
|
settled = FULFILLED;
|
||||||
|
try {
|
||||||
|
value = callback(value);
|
||||||
|
} catch(e) {
|
||||||
|
reject(promise, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!handleThenable(promise, value))
|
||||||
|
{
|
||||||
|
if (settled === FULFILLED)
|
||||||
|
resolve(promise, value);
|
||||||
|
|
||||||
|
if (settled === REJECTED)
|
||||||
|
reject(promise, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleThenable(promise, value) {
|
||||||
|
var resolved;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (promise === value)
|
||||||
|
throw new TypeError('A promises callback cannot return that same promise.');
|
||||||
|
|
||||||
|
if (value && (typeof value === 'function' || typeof value === 'object'))
|
||||||
|
{
|
||||||
|
var then = value.then; // then should be retrived only once
|
||||||
|
|
||||||
|
if (typeof then === 'function')
|
||||||
|
{
|
||||||
|
then.call(value, function(val){
|
||||||
|
if (!resolved)
|
||||||
|
{
|
||||||
|
resolved = true;
|
||||||
|
|
||||||
|
if (value !== val)
|
||||||
|
resolve(promise, val);
|
||||||
|
else
|
||||||
|
fulfill(promise, val);
|
||||||
|
}
|
||||||
|
}, function(reason){
|
||||||
|
if (!resolved)
|
||||||
|
{
|
||||||
|
resolved = true;
|
||||||
|
|
||||||
|
reject(promise, reason);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
if (!resolved)
|
||||||
|
reject(promise, e);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function resolve(promise, value){
|
||||||
|
if (promise === value || !handleThenable(promise, value))
|
||||||
|
fulfill(promise, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
function fulfill(promise, value){
|
||||||
|
if (promise.state_ === PENDING)
|
||||||
|
{
|
||||||
|
promise.state_ = SEALED;
|
||||||
|
promise.data_ = value;
|
||||||
|
|
||||||
|
asyncCall(publishFulfillment, promise);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function reject(promise, reason){
|
||||||
|
if (promise.state_ === PENDING)
|
||||||
|
{
|
||||||
|
promise.state_ = SEALED;
|
||||||
|
promise.data_ = reason;
|
||||||
|
|
||||||
|
asyncCall(publishRejection, promise);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function publish(promise) {
|
||||||
|
var callbacks = promise.then_;
|
||||||
|
promise.then_ = undefined;
|
||||||
|
|
||||||
|
for (var i = 0; i < callbacks.length; i++) {
|
||||||
|
invokeCallback(callbacks[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function publishFulfillment(promise){
|
||||||
|
promise.state_ = FULFILLED;
|
||||||
|
publish(promise);
|
||||||
|
}
|
||||||
|
|
||||||
|
function publishRejection(promise){
|
||||||
|
promise.state_ = REJECTED;
|
||||||
|
publish(promise);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @class
|
||||||
|
*/
|
||||||
|
function Promise(resolver){
|
||||||
|
if (typeof resolver !== 'function')
|
||||||
|
throw new TypeError('Promise constructor takes a function argument');
|
||||||
|
|
||||||
|
if (this instanceof Promise === false)
|
||||||
|
throw new TypeError('Failed to construct \'Promise\': Please use the \'new\' operator, this object constructor cannot be called as a function.');
|
||||||
|
|
||||||
|
this.then_ = [];
|
||||||
|
|
||||||
|
invokeResolver(resolver, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
Promise.prototype = {
|
||||||
|
constructor: Promise,
|
||||||
|
|
||||||
|
state_: PENDING,
|
||||||
|
then_: null,
|
||||||
|
data_: undefined,
|
||||||
|
|
||||||
|
then: function(onFulfillment, onRejection){
|
||||||
|
var subscriber = {
|
||||||
|
owner: this,
|
||||||
|
then: new this.constructor(NOOP),
|
||||||
|
fulfilled: onFulfillment,
|
||||||
|
rejected: onRejection
|
||||||
|
};
|
||||||
|
|
||||||
|
if (this.state_ === FULFILLED || this.state_ === REJECTED)
|
||||||
|
{
|
||||||
|
// already resolved, call callback async
|
||||||
|
asyncCall(invokeCallback, subscriber);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// subscribe
|
||||||
|
this.then_.push(subscriber);
|
||||||
|
}
|
||||||
|
|
||||||
|
return subscriber.then;
|
||||||
|
},
|
||||||
|
|
||||||
|
'catch': function(onRejection) {
|
||||||
|
return this.then(null, onRejection);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Promise.all = function(promises){
|
||||||
|
var Class = this;
|
||||||
|
|
||||||
|
if (!isArray(promises))
|
||||||
|
throw new TypeError('You must pass an array to Promise.all().');
|
||||||
|
|
||||||
|
return new Class(function(resolve, reject){
|
||||||
|
var results = [];
|
||||||
|
var remaining = 0;
|
||||||
|
|
||||||
|
function resolver(index){
|
||||||
|
remaining++;
|
||||||
|
return function(value){
|
||||||
|
results[index] = value;
|
||||||
|
if (!--remaining)
|
||||||
|
resolve(results);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0, promise; i < promises.length; i++)
|
||||||
|
{
|
||||||
|
promise = promises[i];
|
||||||
|
|
||||||
|
if (promise && typeof promise.then === 'function')
|
||||||
|
promise.then(resolver(i), reject);
|
||||||
|
else
|
||||||
|
results[i] = promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!remaining)
|
||||||
|
resolve(results);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
Promise.race = function(promises){
|
||||||
|
var Class = this;
|
||||||
|
|
||||||
|
if (!isArray(promises))
|
||||||
|
throw new TypeError('You must pass an array to Promise.race().');
|
||||||
|
|
||||||
|
return new Class(function(resolve, reject) {
|
||||||
|
for (var i = 0, promise; i < promises.length; i++)
|
||||||
|
{
|
||||||
|
promise = promises[i];
|
||||||
|
|
||||||
|
if (promise && typeof promise.then === 'function')
|
||||||
|
promise.then(resolve, reject);
|
||||||
|
else
|
||||||
|
resolve(promise);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
Promise.resolve = function(value){
|
||||||
|
var Class = this;
|
||||||
|
|
||||||
|
if (value && typeof value === 'object' && value.constructor === Class)
|
||||||
|
return value;
|
||||||
|
|
||||||
|
return new Class(function(resolve){
|
||||||
|
resolve(value);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
Promise.reject = function(reason){
|
||||||
|
var Class = this;
|
||||||
|
|
||||||
|
return new Class(function(resolve, reject){
|
||||||
|
reject(reason);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
})(typeof window != 'undefined' ? window : typeof global != 'undefined' ? global : typeof self != 'undefined' ? self : this);
|
||||||
6
vendors/es6-promise-polyfill/promise.min.js
vendored
Normal file
6
vendors/es6-promise-polyfill/promise.min.js
vendored
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
(function(t){function z(){for(var a=0;a<g.length;a++)g[a][0](g[a][1]);g=[];m=!1}function n(a,b){g.push([a,b]);m||(m=!0,A(z,0))}function B(a,b){function c(a){p(b,a)}function h(a){k(b,a)}try{a(c,h)}catch(d){h(d)}}function u(a){var b=a.owner,c=b.state_,b=b.data_,h=a[c];a=a.then;if("function"===typeof h){c=l;try{b=h(b)}catch(d){k(a,d)}}v(a,b)||(c===l&&p(a,b),c===q&&k(a,b))}function v(a,b){var c;try{if(a===b)throw new TypeError("A promises callback cannot return that same promise.");if(b&&("function"===
|
||||||
|
typeof b||"object"===typeof b)){var h=b.then;if("function"===typeof h)return h.call(b,function(d){c||(c=!0,b!==d?p(a,d):w(a,d))},function(b){c||(c=!0,k(a,b))}),!0}}catch(d){return c||k(a,d),!0}return!1}function p(a,b){a!==b&&v(a,b)||w(a,b)}function w(a,b){a.state_===r&&(a.state_=x,a.data_=b,n(C,a))}function k(a,b){a.state_===r&&(a.state_=x,a.data_=b,n(D,a))}function y(a){var b=a.then_;a.then_=void 0;for(a=0;a<b.length;a++)u(b[a])}function C(a){a.state_=l;y(a)}function D(a){a.state_=q;y(a)}function e(a){if("function"!==
|
||||||
|
typeof a)throw new TypeError("Promise constructor takes a function argument");if(!1===this instanceof e)throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.");this.then_=[];B(a,this)}var f=t.Promise,s=f&&"resolve"in f&&"reject"in f&&"all"in f&&"race"in f&&function(){var a;new f(function(b){a=b});return"function"===typeof a}();"undefined"!==typeof exports&&exports?(exports.Promise=s?f:e,exports.Polyfill=e):"function"==
|
||||||
|
typeof define&&define.amd?define(function(){return s?f:e}):s||(t.Promise=e);var r="pending",x="sealed",l="fulfilled",q="rejected",E=function(){},A="undefined"!==typeof setImmediate?setImmediate:setTimeout,g=[],m;e.prototype={constructor:e,state_:r,then_:null,data_:void 0,then:function(a,b){var c={owner:this,then:new this.constructor(E),fulfilled:a,rejected:b};this.state_===l||this.state_===q?n(u,c):this.then_.push(c);return c.then},"catch":function(a){return this.then(null,a)}};e.all=function(a){if("[object Array]"!==
|
||||||
|
Object.prototype.toString.call(a))throw new TypeError("You must pass an array to Promise.all().");return new this(function(b,c){function h(a){e++;return function(c){d[a]=c;--e||b(d)}}for(var d=[],e=0,f=0,g;f<a.length;f++)(g=a[f])&&"function"===typeof g.then?g.then(h(f),c):d[f]=g;e||b(d)})};e.race=function(a){if("[object Array]"!==Object.prototype.toString.call(a))throw new TypeError("You must pass an array to Promise.race().");return new this(function(b,c){for(var e=0,d;e<a.length;e++)(d=a[e])&&"function"===
|
||||||
|
typeof d.then?d.then(b,c):b(d)})};e.resolve=function(a){return a&&"object"===typeof a&&a.constructor===this?a:new this(function(b){b(a)})};e.reject=function(a){return new this(function(b,c){c(a)})}})("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this);
|
||||||
22
vendors/es6-promise-polyfill/test/test-adapter.js
vendored
Normal file
22
vendors/es6-promise-polyfill/test/test-adapter.js
vendored
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
var assert = require('assert');
|
||||||
|
var Promise = require('../promise').Polyfill;
|
||||||
|
var resolve = Promise.resolve;
|
||||||
|
var reject = Promise.reject;
|
||||||
|
|
||||||
|
function defer(){
|
||||||
|
var deferred = {};
|
||||||
|
|
||||||
|
deferred.promise = new Promise(function(resolve, reject){
|
||||||
|
deferred.resolve = resolve;
|
||||||
|
deferred.reject = reject;
|
||||||
|
});
|
||||||
|
|
||||||
|
return deferred;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
resolved: function(a){ return Promise.resolve(a); },
|
||||||
|
rejected: function(a){ return Promise.reject(a); },
|
||||||
|
deferred: defer,
|
||||||
|
Promise: Promise
|
||||||
|
};
|
||||||
2
vendors/rl/rl-1.5.min.js
vendored
2
vendors/rl/rl-1.5.min.js
vendored
|
|
@ -1,2 +0,0 @@
|
||||||
/*! RainLoop Index Helper v1.5 (c) 2015 RainLoop Team; Licensed under MIT */
|
|
||||||
!function(t,e,n){function r(){}r.prototype.s=t.sessionStorage,r.prototype.t=t.top||t,r.prototype.getHash=function(){var t=null;if(this.s)t=this.s.getItem("__rlA")||null;else if(this.t){var e=this.t.name&&n&&"{"===this.t.name.toString().substr(0,1)?n.parse(this.t.name.toString()):null;t=e?e.__rlA||null:null}return t},r.prototype.setHash=function(){var e=t.rainloopAppData,r=null;this.s?this.s.setItem("__rlA",e&&e.AuthAccountHash?e.AuthAccountHash:""):this.t&&n&&(r={},r.__rlA=e&&e.AuthAccountHash?e.AuthAccountHash:"",this.t.name=n.stringify(r))},r.prototype.clearHash=function(){this.s?this.s.setItem("__rlA",""):this.t&&(this.t.name="")},t._rlhh=new r,t.__rlah=function(){return t._rlhh?t._rlhh.getHash():null},t.__rlah_set=function(){t._rlhh&&t._rlhh.setHash()},t.__rlah_clear=function(){t._rlhh&&t._rlhh.clearHash()},t.__includeScr=function(t){e.write(unescape('%3Cscript data-cfasync="false" type="text/javascript" src="'+t+'"%3E%3C/script%3E'))},t.__includeStyle=function(t){e.write(unescape("%3Cstyle%3E"+t+'"%3E%3C/style%3E'))},t.__showError=function(n){var r=e.getElementById("rl-loading"),s=e.getElementById("rl-loading-error"),l=e.getElementById("rl-loading-error-additional");r&&(r.style.display="none"),s&&(s.style.display="block"),l&&n&&(l.style.display="block",l.innerHTML=n),t.SimplePace&&t.SimplePace.set(100)},t.__simplePace=function(e){t.SimplePace&&t.SimplePace.add(e)},t.__runBoot=function(e,n){t.__APP_BOOT&&!e?t.__APP_BOOT(function(t){t||__showError(n)}):__showError(n)}}(window,window.document,window.JSON);
|
|
||||||
105
vendors/rl/rl.js
vendored
105
vendors/rl/rl.js
vendored
|
|
@ -1,105 +0,0 @@
|
||||||
/*! RainLoop Index Helper v1.5 (c) 2015 RainLoop Team; Licensed under MIT */
|
|
||||||
(function (window, document, JSON, undefined) {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @constructor
|
|
||||||
*/
|
|
||||||
function CRLTopDriver() {}
|
|
||||||
|
|
||||||
CRLTopDriver.prototype.s = window['sessionStorage'] || null;
|
|
||||||
|
|
||||||
CRLTopDriver.prototype.t = window['top'] || window;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return {(string|null)}
|
|
||||||
*/
|
|
||||||
CRLTopDriver.prototype['getHash'] = function() {
|
|
||||||
var mR = null;
|
|
||||||
if (this.s) {
|
|
||||||
mR = this.s['getItem']('__rlA') || null;
|
|
||||||
} else if (this.t) {
|
|
||||||
var mData = this.t['name'] && JSON && '{' === this.t['name']['toString']()['substr'](0, 1) ? JSON['parse'](this.t['name']['toString']()) : null;
|
|
||||||
mR = mData ? (mData['__rlA'] || null) : null;
|
|
||||||
}
|
|
||||||
return mR;
|
|
||||||
};
|
|
||||||
|
|
||||||
CRLTopDriver.prototype['setHash'] = function() {
|
|
||||||
var mData = window['rainloopAppData'], mRes = null;
|
|
||||||
if (this.s) {
|
|
||||||
this.s['setItem']('__rlA', mData && mData['AuthAccountHash'] ? mData['AuthAccountHash'] : '');
|
|
||||||
} else if (this.t && JSON) {
|
|
||||||
mRes = {};
|
|
||||||
mRes['__rlA'] = mData && mData['AuthAccountHash'] ? mData['AuthAccountHash'] : '';
|
|
||||||
this.t['name'] = JSON['stringify'](mRes);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
CRLTopDriver.prototype['clearHash'] = function() {
|
|
||||||
if (this.s) {
|
|
||||||
this.s['setItem']('__rlA', '');
|
|
||||||
} else if (this.t) {
|
|
||||||
this.t['name'] = '';
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
window['_rlhh'] = new CRLTopDriver();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @returns {(string|null)}
|
|
||||||
*/
|
|
||||||
window['__rlah'] = function () {
|
|
||||||
return window['_rlhh'] ? window['_rlhh']['getHash']() : null;
|
|
||||||
};
|
|
||||||
|
|
||||||
window['__rlah_set'] = function () {
|
|
||||||
if (window['_rlhh']) {
|
|
||||||
window['_rlhh']['setHash']();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
window['__rlah_clear'] = function () {
|
|
||||||
if (window['_rlhh']) {
|
|
||||||
window['_rlhh']['clearHash']();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// index function
|
|
||||||
window['__includeScr'] = function (sSrc) {
|
|
||||||
document.write(unescape('%3Csc' + 'ript data-cfasync="false" type="text/jav' + 'ascr' + 'ipt" sr' + 'c="' + sSrc + '"%3E%3C/' + 'scr' + 'ipt%3E'));
|
|
||||||
};
|
|
||||||
|
|
||||||
window['__includeStyle'] = function (sStyles) {
|
|
||||||
document.write(unescape('%3Csty' + 'le%3E' + sStyles + '"%3E%3C/' + 'sty' + 'le%3E'));
|
|
||||||
};
|
|
||||||
|
|
||||||
window['__showError'] = function (sAdditionalError) {
|
|
||||||
var oR = document.getElementById('rl-loading'),
|
|
||||||
oL = document.getElementById('rl-loading-error'),
|
|
||||||
oLA = document.getElementById('rl-loading-error-additional');
|
|
||||||
|
|
||||||
if (oR) {oR.style.display = 'none';}
|
|
||||||
if (oL) {oL.style.display = 'block';}
|
|
||||||
if (oLA && sAdditionalError) { oLA.style.display = 'block'; oLA.innerHTML = sAdditionalError; }
|
|
||||||
if (window.SimplePace) {window.SimplePace.set(100);}
|
|
||||||
};
|
|
||||||
|
|
||||||
window['__simplePace'] = function (nVal) {
|
|
||||||
if (window.SimplePace) {
|
|
||||||
window.SimplePace.add(nVal);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
window['__runBoot'] = function (bWithError, sAdditionalError) {
|
|
||||||
if (window.__APP_BOOT && !bWithError) {
|
|
||||||
window.__APP_BOOT(function (bV) {
|
|
||||||
if (!bV) {
|
|
||||||
__showError(sAdditionalError);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
__showError(sAdditionalError);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
}(window, window.document, window.JSON));
|
|
||||||
|
|
@ -32,6 +32,10 @@ module.exports = {
|
||||||
},
|
},
|
||||||
module: {
|
module: {
|
||||||
loaders: [
|
loaders: [
|
||||||
|
{
|
||||||
|
test: /\.html$/,
|
||||||
|
loader: 'raw'
|
||||||
|
},
|
||||||
{
|
{
|
||||||
test: /\.jsx$/,
|
test: /\.jsx$/,
|
||||||
loader: 'babel',
|
loader: 'babel',
|
||||||
|
|
@ -49,7 +53,7 @@ module.exports = {
|
||||||
'JSON': 'window.JSON',
|
'JSON': 'window.JSON',
|
||||||
'JSEncrypt': 'window.JSEncrypt',
|
'JSEncrypt': 'window.JSEncrypt',
|
||||||
'$LAB': 'window.$LAB',
|
'$LAB': 'window.$LAB',
|
||||||
'progressJs': 'window.rainloopProgressJs',
|
'progressJs': 'window.progressJs',
|
||||||
'queue': 'window.queue',
|
'queue': 'window.queue',
|
||||||
'moment': 'window.moment',
|
'moment': 'window.moment',
|
||||||
'ifvisible': 'window.ifvisible',
|
'ifvisible': 'window.ifvisible',
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue