diff --git a/dev/App/Abstract.jsx b/dev/App/Abstract.jsx
index 4fa97eebc..dab31b074 100644
--- a/dev/App/Abstract.jsx
+++ b/dev/App/Abstract.jsx
@@ -23,7 +23,7 @@ class AbstractApp extends AbstractBoot
{
super();
- this.iframe = $('').appendTo('body');
+ this.iframe = $('').appendTo('body');
Globals.$win.on('error', function (oEvent) {
if (oEvent && oEvent.originalEvent && oEvent.originalEvent.message &&
diff --git a/dev/App/User.jsx b/dev/App/User.jsx
index 379c0c7e4..e23e4d00e 100644
--- a/dev/App/User.jsx
+++ b/dev/App/User.jsx
@@ -1213,13 +1213,6 @@ class AppUser extends AbstractApp
{
kn.hideLoading();
- progressJs.onbeforeend(() => {
- $('.progressjs-container').hide();
- _.delay(() => {
- $('.progressjs-container').remove();
- }, 100);
- });
-
progressJs.set(100).end();
}
else
@@ -1239,7 +1232,6 @@ class AppUser extends AbstractApp
require('Stores/User/Contact').populate();
var
- $LAB = require('$LAB'),
sJsHash = Settings.appSettingsGet('jsHash'),
sStartupUrl = Utils.pString(Settings.settingsGet('StartupUrl')),
iContactsSyncInterval = Utils.pInt(Settings.settingsGet('ContactsSyncInterval')),
@@ -1288,7 +1280,7 @@ class AppUser extends AbstractApp
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) => {
@@ -1298,8 +1290,7 @@ class AppUser extends AbstractApp
{
try
{
-// PgpStore.openpgp.initWorker(Links.openPgpWorkerJs()); // 1.2.0
- PgpStore.openpgp.initWorker({path: Links.openPgpWorkerJs()}); // 2.3.0
+ PgpStore.openpgp.initWorker({path: Links.openPgpWorkerJs()});
}
catch (e)
{
@@ -1321,7 +1312,7 @@ class AppUser extends AbstractApp
}
else
{
- $LAB.script(Links.openPgpJs()).wait(() => {
+ window.jsloader(Links.openPgpJs()).then(() => {
if (window.openpgp)
{
openpgpCallback(window.openpgp);
diff --git a/dev/Common/Booter.jsx b/dev/Common/Booter.jsx
index c0530dcec..039d38cae 100644
--- a/dev/Common/Booter.jsx
+++ b/dev/Common/Booter.jsx
@@ -1,13 +1,20 @@
import window from 'window';
import $ from '$';
+import progressJs from 'progressJs';
import rainLoopStorage from 'Storage/RainLoop';
+let rlAppDataStorage = null;
+
window.__rlah = () => {
return rainLoopStorage ? rainLoopStorage.getHash() : null;
};
+window.__rlah_data = () => {
+ return rlAppDataStorage;
+};
+
window.__rlah_set = () => {
if (rainLoopStorage)
{
@@ -22,20 +29,59 @@ window.__rlah_clear = () => {
}
};
-window.__includeScr = (src) => {
- 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) => {
+function includeStyle(styles)
+{
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
oR = window.document.getElementById('rl-loading'),
oL = window.document.getElementById('rl-loading-error'),
@@ -58,14 +104,14 @@ window.__showError = (additionalError) => {
oLA.innerHTML = additionalError;
}
- if (window.rainloopProgressJs)
+ if (progressJs)
{
- window.rainloopProgressJs.set(100);
+ progressJs.set(100).end();
}
-};
-
-window.__showDescription = (description) => {
+}
+function showDescriptionAndLoading(description)
+{
const
oE = window.document.getElementById('rl-loading'),
oElDesc = window.document.getElementById('rl-loading-desc')
@@ -83,76 +129,81 @@ window.__showDescription = (description) => {
oE.style.opacity = 1;
}, 300);
}
-};
+}
-window.__runBoot = (withError, additionalError) => {
- if (window.__APP_BOOT && !withError) {
+function runMainBoot(withError, additionalError)
+{
+ if (window.__APP_BOOT && !withError)
+ {
window.__APP_BOOT(function (bV) {
- if (!bV) {
- window.__showError(additionalError);
+ if (!bV)
+ {
+ showError(additionalError);
}
});
- } else {
- window.__showError(additionalError);
}
-};
-
-window.__runApp = (BaseAppLibsScriptLink, BaseAppMainScriptLink, BaseAppEditorScriptLink) => {
-
- const appData = window.rainloopAppData;
-
- if (window.$LAB && window.progressJs && appData && appData.TemplatesLink && appData.LangLink)
+ else
{
- const p = window.progressJs();
- window.rainloopProgressJs = p;
+ showError(additionalError);
+ }
+}
+
+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.start().set(5);
- window.$LAB
- .script(function () {
- return [
- {src: BaseAppLibsScriptLink, type: 'text/javascript', charset: 'utf-8'}
- ];
- })
- .wait(function () {
+ const
+ libs = window.jsloader(appData.StaticLibJsLink).then(() => {
+ if (window.$)
+ {
+ if (!window.$('#rl-check').is(':visible'))
+ {
+ window.$('html').addClass('no-css');
+ throw new Error('no-css');
+ }
- p.set(20);
+ window.$('#rl-check').remove();
- if (appData.IncludeBackground && $) {
- $('#rl-bg').attr('style', 'background-image: none !important;')
- .backstretch(appData.IncludeBackground.replace('{{USER}}',
- (window.__rlah ? window.__rlah() || '0' : '0')), {fade: 100, centeredX: true, centeredY: true})
- .removeAttr('style')
- ;
+ if (appData.IncludeBackground)
+ {
+ window.$('#rl-bg').attr('style', 'background-image: none !important;')
+ .backstretch(appData.IncludeBackground.replace('{{USER}}',
+ (window.__rlah ? (window.__rlah() || '0') : '0')), {fade: 100, centeredX: true, centeredY: true})
+ .removeAttr('style')
+ ;
+ }
}
- })
- .script(function () {
- return [
- {src: appData.TemplatesLink, type: 'text/javascript', charset: 'utf-8'},
- {src: appData.LangLink, type: 'text/javascript', charset: 'utf-8'}
- ];
- })
- .wait(function () {
+ }),
+ common = window.Promise.all([
+ window.jsloader(appData.TemplatesLink),
+ window.jsloader(appData.LangLink)
+ ])
+ ;
+
+ window.Promise.all([libs, common])
+ .then(() => {
p.set(30);
- })
- .script(function () {
- return {src: BaseAppMainScriptLink, type: 'text/javascript', charset: 'utf-8'};
- })
- .wait(function () {
+ return window.jsloader(appData.StaticAppJsLink);
+ }).then(() => {
p.set(50);
- })
- .script(function () {
- return appData.PluginsLink ? {src: appData.PluginsLink, type: 'text/javascript', charset: 'utf-8'} : null;
- })
- .wait(function () {
+ return appData.PluginsLink ? window.jsloader(appData.PluginsLink) : window.Promise.resolve();
+ }).then(() => {
p.set(70);
- window.__runBoot(false);
- })
- .script(function () {
- return {src: BaseAppEditorScriptLink, type: 'text/javascript', charset: 'utf-8'};
- })
- .wait(function () {
+ runMainBoot(false);
+ }).catch((e) => {
+ runMainBoot(true);
+ throw e;
+ }).then(() => {
+ return window.jsloader(appData.StaticEditorJsLink);
+ }).then(() => {
if (window.CKEDITOR && window.__initEditor) {
window.__initEditor();
window.__initEditor = null;
@@ -162,6 +213,41 @@ window.__runApp = (BaseAppLibsScriptLink, BaseAppMainScriptLink, BaseAppEditorSc
}
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());
}
};
+
diff --git a/dev/Common/Loader.jsx b/dev/Common/Loader.jsx
new file mode 100644
index 000000000..f4417d5a6
--- /dev/null
+++ b/dev/Common/Loader.jsx
@@ -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);
+ });
+};
diff --git a/dev/Common/Utils.js b/dev/Common/Utils.js
index 5d3f8e840..53f6650d2 100644
--- a/dev/Common/Utils.js
+++ b/dev/Common/Utils.js
@@ -1419,7 +1419,7 @@
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)
{
var
- oThemeLink = $('#rlThemeLink'),
- oThemeStyle = $('#rlThemeStyle'),
+ oThemeLink = $('#app-theme-link'),
+ oThemeStyle = $('#app-theme-style'),
sUrl = oThemeLink.attr('href')
;
@@ -1576,7 +1576,7 @@
{
if (oThemeLink && oThemeLink[0] && (!oThemeStyle || !oThemeStyle[0]))
{
- oThemeStyle = $('');
+ oThemeStyle = $('');
oThemeLink.after(oThemeStyle);
oThemeLink.remove();
}
diff --git a/dev/Html/Layout.html b/dev/Html/Layout.html
new file mode 100644
index 000000000..12e6e261b
--- /dev/null
+++ b/dev/Html/Layout.html
@@ -0,0 +1,24 @@
+
+
+
+ An error occurred.
Please refresh the page and try again.
+
+
+
+
+
\ No newline at end of file
diff --git a/dev/Storage/RainLoop.jsx b/dev/Storage/RainLoop.jsx
index 0ebc7ffe1..b404f6372 100644
--- a/dev/Storage/RainLoop.jsx
+++ b/dev/Storage/RainLoop.jsx
@@ -32,7 +32,7 @@ class RainLoopStorage
setHash() {
const
key = 'AuthAccountHash',
- appData = window.rainloopAppData
+ appData = window.__rlah_data()
;
if (this.s)
{
diff --git a/dev/Storage/Settings.jsx b/dev/Storage/Settings.jsx
index a14ba2136..48d9e526c 100644
--- a/dev/Storage/Settings.jsx
+++ b/dev/Storage/Settings.jsx
@@ -8,7 +8,7 @@ class SettingsStorage
appSettings = {};
constructor() {
- this.settings = window.rainloopAppData || {};
+ this.settings = window.__rlah_data() || {};
this.settings = Utils.isNormal(this.settings) ? this.settings : {};
this.appSettings = this.settings.System || null;
diff --git a/dev/Styles/Layout.less b/dev/Styles/Layout.less
index 41bbac63c..5d61f4a42 100644
--- a/dev/Styles/Layout.less
+++ b/dev/Styles/Layout.less
@@ -349,7 +349,7 @@ html.rl-ctrl-key-pressed {
#rl-loading, #rl-loading-error {
position: absolute;
font-size: 30px;
- line-height: 100%;
+ line-height: 130%;
top: 50%;
width: 100%;
height: 65px;
@@ -370,6 +370,14 @@ html.rl-ctrl-key-pressed {
font-size: 20px;
}
+#rl-app{
+ display: none;
+}
+
+#rl-check{
+ display: block;
+}
+
html.rl-mobile .hide-on-mobile {
display: none !important;
}
diff --git a/dev/Styles/_End.less b/dev/Styles/_End.less
index ed0305d93..de493e035 100644
--- a/dev/Styles/_End.less
+++ b/dev/Styles/_End.less
@@ -28,10 +28,6 @@
opacity: 0;
}
-#rl-check {
- display: block;
-}
-
.opentip-container {
z-index: 2001 !important;
diff --git a/dev/boot.jsx b/dev/boot.jsx
index e15efc72e..16d8c2049 100644
--- a/dev/boot.jsx
+++ b/dev/boot.jsx
@@ -1,12 +1,27 @@
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('modernizr/modernizr-custom.js');
+
require('Common/Booter.jsx');
-import {$LAB} from 'labjs/LAB.src.js';
-import {progressJs} from 'progress.js/src/progress.js';
-
-window.$LAB = $LAB;
-window.progressJs = progressJs;
+if (window.__runBoot)
+{
+ window.__runBoot();
+}
diff --git a/dev/bootstrap.jsx b/dev/bootstrap.jsx
index a82d5ce64..e25b8291a 100644
--- a/dev/bootstrap.jsx
+++ b/dev/bootstrap.jsx
@@ -48,17 +48,10 @@ export default (App) => {
window['rl']['EmailModel'] = EmailModel;
window['rl']['Enums'] = Enums;
- window['__APP_BOOT'] = function (fCall) {
+ window.__APP_BOOT = function (fCall) {
$(_.delay(function () {
- if (!$('#rl-check').is(':visible'))
- {
- Globals.$html.addClass('no-css');
- }
-
- $('#rl-check').remove();
-
if (window['rainloopTEMPLATES'] && window['rainloopTEMPLATES'][0])
{
$('#rl-templates').html(window['rainloopTEMPLATES'][0]);
@@ -79,7 +72,7 @@ export default (App) => {
fCall(false);
}
- window['__APP_BOOT'] = null;
+ window.__APP_BOOT = null;
}, 10));
};
diff --git a/gulpfile.js b/gulpfile.js
index e5bcb1c76..03e562df3 100644
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -97,7 +97,7 @@ function copyFile(sFile, sNewFile, callback)
callback();
}
-cfg.paths.globjs = 'dev/**/*.{js,jsx}';
+cfg.paths.globjs = 'dev/**/*.{js,jsx,html}';
cfg.paths.globjsonly = 'dev/**/*.js';
cfg.paths.globjsxonly = 'dev/**/*.jsx';
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() {
-
return gulp.src(cfg.paths.staticCSS + cfg.paths.less.main.name, {read: false})
.pipe(require('gulp-rimraf')());
});
diff --git a/package.json b/package.json
index 91b9271e7..3e1a367d0 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,7 @@
"name": "RainLoop",
"title": "RainLoop Webmail",
"version": "1.10.0",
- "release": "108",
+ "release": "112",
"ownCloudPackageVersion": "4.16",
"description": "Simple, modern & fast web-based email client",
"homepage": "http://rainloop.net",
@@ -84,6 +84,7 @@
"lodash": "~3.9.3",
"node-fs": "*",
"node-notifier": "~4.2.3",
+ "raw-loader": "^0.5.1",
"rimraf": "*",
"webpack": "*"
}
diff --git a/phpunit.xml b/phpunit.xml
new file mode 100644
index 000000000..d890f0d88
--- /dev/null
+++ b/phpunit.xml
@@ -0,0 +1,8 @@
+
+
+
+
+ tests
+
+
+
\ No newline at end of file
diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Actions.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Actions.php
index 1fe5efd21..e520ff1da 100644
--- a/rainloop/v/0.0.0/app/libraries/RainLoop/Actions.php
+++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Actions.php
@@ -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 (!$bAdmin)
@@ -1923,14 +1918,11 @@ NewThemeLink IncludeCss LoadingDescriptionEsc TemplatesLink LangLink IncludeBack
}
}
- $sPluginsLink = '';
- if (0 < $this->Plugins()->Count() && $this->Plugins()->HaveJs($bAdmin))
- {
- $sPluginsLink = './?/Plugins/0/'.($bAdmin ? 'Admin' : 'User').'/'.$sStaticCache.'/';
- }
+ $sTheme = $this->ValidateTheme($sTheme, $bMobile);
+ $sStaticCache = $this->StaticCache();
$aResult['Theme'] = $sTheme;
- $aResult['NewThemeLink'] = $sNewThemeLink;
+ $aResult['NewThemeLink'] = $this->ThemeLink($sTheme, $bAdmin);
$aResult['Language'] = $this->ValidateLanguage($sLanguage, '', false);
$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['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').'/'.
($bAdmin ? $aResult['LanguageAdmin'] : $aResult['Language']).'/'.$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'] : 'Plain';
@@ -9057,6 +9061,29 @@ NewThemeLink IncludeCss LoadingDescriptionEsc TemplatesLink LangLink IncludeBack
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
*
@@ -9694,6 +9721,18 @@ NewThemeLink IncludeCss LoadingDescriptionEsc TemplatesLink LangLink IncludeBack
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
*/
diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Service.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Service.php
index 7ddfae8c7..940a78722 100644
--- a/rainloop/v/0.0.0/app/libraries/RainLoop/Service.php
+++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Service.php
@@ -219,7 +219,7 @@ class Service
}
$sResult .= '';
+ $sResult .= ']-->';
}
// Output result
@@ -259,9 +259,7 @@ class Service
*/
private function staticPath($sPath)
{
- $sResult = \RainLoop\Utils::WebStaticPath().$sPath;
- return $sResult.(false === \strpos($sResult, '?') ? '?' : '&').
- ($this->oActions->IsOpen() ? 'v=community' : 'v=standard');
+ return $this->oActions->StaticPath($sPath);
}
/**
@@ -283,42 +281,27 @@ class Service
$sFaviconUrl = (string) $this->oActions->Config()->Get('webmail', 'favicon_url', '');
- $aData = array(
- 'Language' => $sLanguage,
- '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';
+ $sFaviconPngLink = $sFaviconUrl ? $sFaviconUrl : $this->staticPath('apple-touch-icon.png');
+ $sAppleTouchLink = $sFaviconUrl ? '' : $this->staticPath('apple-touch-icon.png');
$aTemplateParameters = array(
- '{{BaseAppDataScriptLink}}' => ($bAdmin ? './?/AdminAppData' : './?/AppData').(0 < \count($aAdd) ? '@'.\implode('-', $aAdd) : '').'/',
- '{{BaseAppFaviconPngLinkTag}}' => $aData['FaviconPngLink'] ? '' : '',
- '{{BaseAppFaviconTouchLinkTag}}' => $aData['AppleTouchLink'] ? '' : '',
- '{{BaseAppAppleTouchFile}}' => $aData['AppleTouchLink'],
- '{{BaseAppMainCssLink}}' => $aData['AppCssLink'],
- '{{BaseAppBootScriptLink}}' => $aData['BootJsLink'],
- '{{BaseAppLibsScriptLink}}' => $aData['LibJsLink'],
- '{{BaseAppEditorScriptLink}}' => $aData['EditorJsLink'],
- '{{BaseAppOpenPgpScriptLink}}' => $aData['OpenPgpJsLink'],
- '{{BaseAppMainCommonScriptLink}}' => $aData['AppJsCommonLink'],
- '{{BaseAppMainScriptLink}}' => $aData['AppJsLink'],
- '{{BaseVersion}}' => APP_VERSION,
+ '{{BaseAppFaviconPngLinkTag}}' => $sFaviconPngLink ? '' : '',
+ '{{BaseAppFaviconTouchLinkTag}}' => $sAppleTouchLink ? '' : '',
+ '{{BaseAppMainCssLink}}' => $this->staticPath('css/app'.($bAppCssDebug ? '' : '.min').'.css'),
+ '{{BaseAppThemeCssLink}}' => $this->oActions->ThemeLink($sTheme, $bAdmin),
+ '{{BaseAppBootScriptLink}}' => $this->staticPath('js/'.($bAppJsDebug ? '' : 'min/').'boot.js'),
'{{BaseViewport}}' => $bMobile ? 'width=device-width,initial-scale=1,user-scalable=no' : 'width=950,maximum-scale=2',
- '{{BaseDir}}' => 'ltr'
-// '{{BaseDir}}' => \in_array($aData['Language'], array('ar', 'he', 'ur')) ? 'rtl' : 'ltr'
+ '{{BaseDir}}' => false && \in_array($sLanguage, array('ar', 'he', 'ur')) ? 'rtl' : 'ltr'
);
+ $aTemplateParameters['{{RainloopBootData}}'] = \json_encode(array(
+ 'admin' => $bAdmin,
+ 'language' => $sLanguage,
+ 'theme' => $sTheme,
+ 'mobile' => $bMobile,
+ 'mobileDevice' => $bMobileDevice
+ ));
+
$aTemplateParameters['{{BaseHash}}'] = \md5(
\implode('~', array(
$bAdmin ? '1' : '0',
diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/ServiceActions.php b/rainloop/v/0.0.0/app/libraries/RainLoop/ServiceActions.php
index 04236a453..87e27da8d 100644
--- a/rainloop/v/0.0.0/app/libraries/RainLoop/ServiceActions.php
+++ b/rainloop/v/0.0.0/app/libraries/RainLoop/ServiceActions.php
@@ -1369,9 +1369,8 @@ class ServiceActions
private function compileAppData($aAppData, $bWrapByScriptTag = true)
{
return
- ($bWrapByScriptTag ? '' : '')
;
}
diff --git a/rainloop/v/0.0.0/app/libraries/RainLoop/Utils.php b/rainloop/v/0.0.0/app/libraries/RainLoop/Utils.php
index 2872eed3f..83b20418a 100644
--- a/rainloop/v/0.0.0/app/libraries/RainLoop/Utils.php
+++ b/rainloop/v/0.0.0/app/libraries/RainLoop/Utils.php
@@ -475,12 +475,13 @@ class Utils
public static function ClearHtmlOutput($sHtml)
{
// return $sHtml;
- return \str_replace('> <', '><',
+ return \trim(\str_replace('> <', '><',
+ \str_replace('" />', '"/>',
\preg_replace('/[\s]+ /i', ' ',
\preg_replace('/ [\s]+/i', ' ',
\preg_replace('/[\r\n\t]+/', ' ',
$sHtml
- ))));
+ ))))));
}
/**
diff --git a/rainloop/v/0.0.0/app/templates/Index.html b/rainloop/v/0.0.0/app/templates/Index.html
index c6221c64f..a4e681d84 100644
--- a/rainloop/v/0.0.0/app/templates/Index.html
+++ b/rainloop/v/0.0.0/app/templates/Index.html
@@ -1,74 +1,29 @@
-
-
-
-
-
-
-
+
+
+
+
+
+
-
- {{BaseAppFaviconPngLinkTag}}{{BaseAppFaviconTouchLinkTag}}
+ {{BaseAppFaviconPngLinkTag}}
+ {{BaseAppFaviconTouchLinkTag}}
+
-
-
-
-
-
-
+
+
-
-
-
- An Error occurred,
-
- please refresh the page and try again.
-
-
-
-
-
-
-
+
diff --git a/rainloop/v/0.0.0/app/templates/Themes/template.less b/rainloop/v/0.0.0/app/templates/Themes/template.less
index 2961b3b47..1901534ac 100644
--- a/rainloop/v/0.0.0/app/templates/Themes/template.less
+++ b/rainloop/v/0.0.0/app/templates/Themes/template.less
@@ -187,9 +187,39 @@
.thm-rgba-background-color(@message-background-color, @message-rgba-background-color);
}
+#rl-app{
+ display: block;
+}
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 {
color: #333;
background-color: #aaa;
diff --git a/rainloop/v/0.0.0/app/templates/Views/User/SystemDropDown.html b/rainloop/v/0.0.0/app/templates/Views/User/SystemDropDown.html
index 2e4974e0f..5a1c3ed9f 100644
--- a/rainloop/v/0.0.0/app/templates/Views/User/SystemDropDown.html
+++ b/rainloop/v/0.0.0/app/templates/Views/User/SystemDropDown.html
@@ -3,13 +3,12 @@