diff --git a/dev/App/Abstract.js b/dev/App/Abstract.js index 38037f27f..a101ec952 100644 --- a/dev/App/Abstract.js +++ b/dev/App/Abstract.js @@ -1,9 +1,6 @@ import ko from 'ko'; -import { - elementById, - Settings -} from 'Common/Globals'; +import { Settings, SettingsGet } from 'Common/Globals'; import { logoutLink } from 'Common/Links'; import { i18nToNodes, initOnStartOrLangChange } from 'Common/Translator'; @@ -37,6 +34,12 @@ export class AbstractApp { } } + refresh() { +// rl.adminArea() || !translatorReload(false, ); + rl.adminArea() || LanguageStore.language(SettingsGet('Language')); + this.start(); + } + bootstart() { const register = (key, ClassObject, templateID) => ko.components.register(key, { template: { element: templateID || (key + 'Component') }, @@ -68,14 +71,7 @@ export class AbstractApp { LanguageStore.populate(); ThemeStore.populate(); - } - /** - * @returns {void} - */ - hideLoading() { - elementById('rl-content').hidden = false; - elementById('rl-loading').remove(); + this.start(); } - } diff --git a/dev/App/Admin.js b/dev/App/Admin.js index 7dd317f31..acdb3278c 100644 --- a/dev/App/Admin.js +++ b/dev/App/Admin.js @@ -16,8 +16,7 @@ class AdminApp extends AbstractApp { this.weakPassword = ko.observable(false); } - bootstart() { - super.bootstart(); + start() { if (!Settings.app('allowAdminPanel')) { rl.route.root(); setTimeout(() => location.href = '/', 1); @@ -27,7 +26,6 @@ class AdminApp extends AbstractApp { } else { startScreens([LoginAdminScreen]); } - this.hideLoading(); } } diff --git a/dev/App/User.js b/dev/App/User.js index c2a1ae844..09d15182c 100644 --- a/dev/App/User.js +++ b/dev/App/User.js @@ -1,6 +1,6 @@ import 'External/User/ko'; -import { isArray, arrayLength, pInt, pString } from 'Common/Utils'; +import { isArray, arrayLength, pInt, pString, forEachObjectValue } from 'Common/Utils'; import { isPosNumeric, delegateRunOnDestroy, mailToHelper } from 'Common/UtilsUser'; import { @@ -187,7 +187,7 @@ class AppUser extends AbstractApp { const sTrashFolder = FolderUserStore.trashFolder(), sSpamFolder = FolderUserStore.spamFolder(); - Object.values(this.moveCache).forEach(item => { + forEachObjectValue(this.moveCache, item => { const isSpam = sSpamFolder === item.To, isTrash = sTrashFolder === item.To, isHam = !isSpam && sSpamFolder === item.From && getFolderInboxName() === item.To; @@ -810,7 +810,9 @@ class AppUser extends AbstractApp { return event.returnValue = "Are you sure you want to exit?"; } }, {capture: true}); + } + start() { if (SettingsGet('Auth')) { rl.setWindowTitle(i18n('GLOBAL/LOADING')); @@ -830,7 +832,6 @@ class AppUser extends AbstractApp { MailBoxUserScreen, SettingsUserScreen ]); - this.hideLoading(); setInterval(() => { const cF = FolderUserStore.currentFolderFullNameRaw(), @@ -916,7 +917,6 @@ class AppUser extends AbstractApp { } else { startScreens([LoginUserScreen]); - this.hideLoading(); } } diff --git a/dev/Common/Translator.js b/dev/Common/Translator.js index f8201b412..2c21f2391 100644 --- a/dev/Common/Translator.js +++ b/dev/Common/Translator.js @@ -133,7 +133,7 @@ export const * @param {boolean} admin * @param {string} language */ - reload = (admin, language) => + translatorReload = (admin, language) => new Promise((resolve, reject) => { const script = createElement('script'); script.onload = () => { diff --git a/dev/Common/Utils.js b/dev/Common/Utils.js index 4fdeefc9d..de4505bc1 100644 --- a/dev/Common/Utils.js +++ b/dev/Common/Utils.js @@ -10,6 +10,8 @@ export const isFunction = v => typeof v === 'function', pString = value => null != value ? '' + value : '', + forEachObjectValue = (obj, fn) => Object.values(obj).forEach(fn), + pInt = (value, defaultValue = 0) => { value = parseInt(value, 10); return isNaN(value) || !isFinite(value) ? defaultValue : value; diff --git a/dev/Knoin/AbstractModel.js b/dev/Knoin/AbstractModel.js index 50f48e065..853af82e4 100644 --- a/dev/Knoin/AbstractModel.js +++ b/dev/Knoin/AbstractModel.js @@ -1,4 +1,4 @@ -import { isArray, isFunction, addObservablesTo, addComputablesTo } from 'Common/Utils'; +import { isArray, isFunction, addObservablesTo, addComputablesTo, forEachObjectValue } from 'Common/Utils'; function dispose(disposable) { if (disposable && isFunction(disposable.dispose)) { @@ -52,7 +52,7 @@ export class AbstractModel { this.subscribables.forEach(dispose); /** clear object entries */ // Object.entries(this).forEach(([key, value]) => { - Object.values(this).forEach(value => { + forEachObjectValue(this, value => { /** clear CollectionModel */ let arr = ko.isObservableArray(value) ? value() : value; arr && arr.onDestroy && value.onDestroy(); diff --git a/dev/Knoin/Knoin.js b/dev/Knoin/Knoin.js index 49f9ebb5b..064ada109 100644 --- a/dev/Knoin/Knoin.js +++ b/dev/Knoin/Knoin.js @@ -1,12 +1,14 @@ import ko from 'ko'; -import { doc, $htmlCL } from 'Common/Globals'; -import { isFunction } from 'Common/Utils'; +import { doc, $htmlCL, elementById } from 'Common/Globals'; +import { isFunction, forEachObjectValue } from 'Common/Utils'; -let currentScreen = null, +let + SCREENS = {}, + currentScreen = null, defaultScreenName = ''; -const SCREENS = {}, +const autofocus = dom => { const af = dom.querySelector('[autofocus]'); af && af.focus(); @@ -123,6 +125,15 @@ const SCREENS = {}, }); }, + hideScreen = (screenToHide, destroy) => { + screenToHide.onHide && screenToHide.onHide(); + forEachViewModel(screenToHide, (vm, dom) => { + dom.hidden = true; + vm.onHide && vm.onHide(); + destroy && vm.viewModelDom.remove(); + }); + }, + /** * @param {string} screenName * @param {string} subPart @@ -167,12 +178,7 @@ const SCREENS = {}, setTimeout(() => { // hide screen if (currentScreen && !isSameScreen) { - currentScreen.onHide && currentScreen.onHide(); - - forEachViewModel(currentScreen, (vm, dom) => { - dom.hidden = true; - vm.onHide && vm.onHide(); - }); + hideScreen(currentScreen); } // -- @@ -275,6 +281,12 @@ export const * @returns {void} */ startScreens = screensClasses => { + hasher.clear(); + forEachObjectValue(SCREENS, screen => hideScreen(screen, 1)); + SCREENS = {}; + currentScreen = null, + defaultScreenName = ''; + screensClasses.forEach(CScreen => { if (CScreen) { const vmScreen = new CScreen(), @@ -284,7 +296,7 @@ export const } }); - Object.values(SCREENS).forEach(vmScreen => vmScreen.onStart()); + forEachObjectValue(SCREENS, vmScreen => vmScreen.onStart()); const cross = new Crossroads(); cross.addRoute(/^([a-zA-Z0-9-]*)\/?(.*)$/, screenOnRoute); @@ -294,6 +306,10 @@ export const setTimeout(() => $htmlCL.remove('rl-started-trigger'), 100); setTimeout(() => $htmlCL.add('rl-started-delay'), 200); + + const c = elementById('rl-content'), l = elementById('rl-loading'); + c && (c.hidden = false); + l && l.remove(); }, decorateKoCommands = (thisArg, commands) => diff --git a/dev/Settings/Admin/General.js b/dev/Settings/Admin/General.js index f02c7b78d..18063f4be 100644 --- a/dev/Settings/Admin/General.js +++ b/dev/Settings/Admin/General.js @@ -13,7 +13,7 @@ import { import { Capa, SaveSettingsStep } from 'Common/Enums'; import { Settings, SettingsGet } from 'Common/Globals'; -import { reload as translatorReload, convertLangName } from 'Common/Translator'; +import { translatorReload, convertLangName } from 'Common/Translator'; import { showScreenPopup } from 'Knoin/Knoin'; diff --git a/dev/Settings/User/Filters.js b/dev/Settings/User/Filters.js index 61da5c159..c1cb4bb06 100644 --- a/dev/Settings/User/Filters.js +++ b/dev/Settings/User/Filters.js @@ -1,7 +1,7 @@ import ko from 'ko'; import { getNotification } from 'Common/Translator'; -import { addObservablesTo } from 'Common/Utils'; +import { addObservablesTo, forEachObjectValue } from 'Common/Utils'; import { delegateRunOnDestroy } from 'Common/UtilsUser'; import { SieveUserStore } from 'Stores/User/Sieve'; @@ -50,7 +50,7 @@ export class FiltersUserSettings /*extends AbstractViewSettings*/ { data.Result.Scripts.map(aItem => SieveScriptModel.reviveFromJson(aItem)).filter(v => v) ); */ - Object.values(data.Result.Scripts).forEach(value => { + forEachObjectValue(data.Result.Scripts, value => { value = SieveScriptModel.reviveFromJson(value); value && this.scripts.push(value) }); diff --git a/dev/Settings/User/General.js b/dev/Settings/User/General.js index 837c96a60..9c1b130e3 100644 --- a/dev/Settings/User/General.js +++ b/dev/Settings/User/General.js @@ -4,7 +4,7 @@ import { SaveSettingsStep } from 'Common/Enums'; import { EditorDefaultType, Layout } from 'Common/EnumsUser'; import { Settings, SettingsGet } from 'Common/Globals'; import { isArray, settingsSaveHelperSimpleFunction, addObservablesTo, addSubscribablesTo, addComputablesTo } from 'Common/Utils'; -import { i18n, trigger as translatorTrigger, reload as translatorReload, convertLangName } from 'Common/Translator'; +import { i18n, trigger as translatorTrigger, translatorReload, convertLangName } from 'Common/Translator'; import { showScreenPopup } from 'Knoin/Knoin'; diff --git a/dev/View/Admin/Login.js b/dev/View/Admin/Login.js index 2a67625d2..42986b9ba 100644 --- a/dev/View/Admin/Login.js +++ b/dev/View/Admin/Login.js @@ -51,12 +51,12 @@ class LoginAdminView extends AbstractViewCenter { this.submitRequest(true); Remote.adminLogin( - iError => { + (iError, oData) => { if (iError) { this.submitRequest(false); this.submitError(getNotification(iError)); } else { - rl.route.reload(); + rl.setData(oData.Result); } }, name, diff --git a/dev/View/User/Login.js b/dev/View/User/Login.js index 3efdfca5c..d71a309d7 100644 --- a/dev/View/User/Login.js +++ b/dev/View/User/Login.js @@ -3,7 +3,7 @@ import ko from 'ko'; import { Notification } from 'Common/Enums'; import { ClientSideKeyName } from 'Common/EnumsUser'; import { Settings, SettingsGet } from 'Common/Globals'; -import { getNotification, reload as translatorReload, convertLangName } from 'Common/Translator'; +import { getNotification, translatorReload, convertLangName } from 'Common/Translator'; import { LanguageStore } from 'Stores/Language'; @@ -116,7 +116,8 @@ class LoginUserView extends AbstractViewCenter { Notification.UnknownNotification)); this.submitErrorAddidional((oData && oData.ErrorMessageAdditional) || ''); } else { - rl.route.reload(); + rl.setData(oData.Result); +// rl.route.reload(); } }, data diff --git a/dev/boot.js b/dev/boot.js index d8d56a4cf..8b7ff29b7 100644 --- a/dev/boot.js +++ b/dev/boot.js @@ -68,6 +68,11 @@ win.rl = { showError(e.message); throw e; }); + }, + + setData: appData => { + RL_APP_DATA = appData; + rl.app.refresh(); } }; diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Admin.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Admin.php index 03eea0e6d..9d8b14c01 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Admin.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Admin.php @@ -198,7 +198,7 @@ trait Admin $sToken = $this->getAdminToken(); $this->setAdminAuthToken($sToken); - return $this->DefaultResponse(__FUNCTION__, $sToken ? true : false); + return $this->DefaultResponse(__FUNCTION__, $sToken ? $this->AppData(true) : false); } public function DoAdminLogout() : array diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/User.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/User.php index 683525a1b..f07c8b5d5 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/User.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/User.php @@ -58,7 +58,7 @@ trait User } } - return $this->TrueResponse(__FUNCTION__); + return $this->DefaultResponse(__FUNCTION__, $this->AppData(false)); } /** diff --git a/vendors/routes/hasher.js b/vendors/routes/hasher.js index f74937ddf..ca8143a45 100644 --- a/vendors/routes/hasher.js +++ b/vendors/routes/hasher.js @@ -11,8 +11,6 @@ // Private //-------------------------------------------------------------------------------------- - var _hash, _bindings = []; - const _hashValRegexp = /#(.*)$/, _hashRegexp = /^#/, @@ -44,11 +42,12 @@ // we should store raw value _registerChange(path); if (path === _hash) { + path = '#' + encodeURI(path) // we check if path is still === _hash to avoid error in // case of multiple consecutive redirects [issue #39] replace - ? location.replace('#' + encodeURI(path)) - : (location.hash = '#' + encodeURI(path)); + ? location.replace(path) + : (location.hash = path); } } }, @@ -58,6 +57,10 @@ //-------------------------------------------------------------------------------------- hasher = /** @lends hasher */ { + clear : () => { + _bindings = []; + hasher.active = true; + }, /** * Signal dispatched when hash value changes. @@ -74,16 +77,7 @@ *
  • hasher won't dispatch CHANGE events by manually typing a new value or pressing the back/forward buttons before calling this method.
  • * */ - init : () => { - hasher.init = ()=>0; - _hash = _getWindowHash(); - - //thought about branching/overloading hasher.init() to avoid checking multiple times but - //don't think worth doing it since it probably won't be called multiple times. - addEventListener('hashchange', _checkHistory); - - hasher.dispatch(_trimHash(_hash)); - }, + init : () => hasher.dispatch(_trimHash(_hash)), /** * Set Hash value, generating a new history record. @@ -101,5 +95,10 @@ replaceHash : (...path) => _setHash(path, true) }; + var _hash = _getWindowHash(), + _bindings = []; + + addEventListener('hashchange', _checkHistory); + global.hasher = hasher; })(this);