diff --git a/packages/app-shell/src/app-shell.js b/packages/app-shell/src/app-shell.js index c6b136c4aa7d5b4eb62cb5fb137e9a43683f3573..e30650baa20b65b520e2a486b3eeb0a593a46d86 100644 --- a/packages/app-shell/src/app-shell.js +++ b/packages/app-shell/src/app-shell.js @@ -219,14 +219,21 @@ export class AppShell extends ScopedElementsMixin(DBPLitElement) { this.router = new Router(routes, { routeName: 'mainRoute', getState: () => { - return { + let state = { component: this.activeView, lang: this.lang, }; + return state; }, setState: (state) => { this.updateLangIfChanged(state.lang); this.switchComponent(state.component); + }, + getDefaultState: () => { + return { + lang: 'de', + component: this.routes[0], + }; } }, { baseUrl: new URL(this.basePath, window.location).pathname.replace(/\/$/, ''), diff --git a/packages/app-shell/src/router.js b/packages/app-shell/src/router.js index c05b899c25235e66d9e50f3231fdbcf62cf7daab..e4ed40c081d714ca82d9ce70624d2a2adca8dbce 100644 --- a/packages/app-shell/src/router.js +++ b/packages/app-shell/src/router.js @@ -17,12 +17,14 @@ export class Router { constructor(routes, options, unioptions) { this.getState = options.getState; this.setState = options.setState; + this.getDefaultState = options.getDefaultState; // XXX: We only have one route atm // If we need more we need to pass the route name to each function this.routeName = options.routeName; console.assert(this.getState); console.assert(this.setState); + console.assert(this.getDefaultState); console.assert(this.routeName); // https://github.com/kriasoft/universal-router @@ -39,15 +41,16 @@ export class Router { */ setStateFromCurrentLocation() { const oldPathName = location.pathname; + this.router.resolve({pathname: oldPathName}).then(page => { const newPathname = this.getPathname(page); // In case of a router redirect, set the new location if (newPathname !== oldPathName) { const referrerUrl = location.href; - if (!newPathname.endsWith('/root')) { - window.history.replaceState({}, '', newPathname); - } + window.history.replaceState({}, '', newPathname); this.dispatchLocationChanged(referrerUrl); + } else if (this.isBasePath(oldPathName)) { + page = this.getDefaultState(); } this.setState(page); }).catch((e) => { @@ -56,6 +59,10 @@ export class Router { }); } + isBasePath(pathname) { + return pathname.replace(/\/$/, '') === this.router.baseUrl.replace(/\/$/, ''); + } + /** * Update the router after some internal state change. */ @@ -67,10 +74,14 @@ export class Router { const oldPathname = location.pathname; if (newPathname === oldPathname) return; - const referrerUrl = location.href; - if (!newPathname.endsWith('/root')) { - window.history.pushState({}, '', newPathname); + + const defaultPathname = this.getPathname(this.getDefaultState()); + if (newPathname === defaultPathname && this.isBasePath(oldPathname)) { + return; } + + const referrerUrl = location.href; + window.history.pushState({}, '', newPathname); this.dispatchLocationChanged(referrerUrl); }); } @@ -107,12 +118,12 @@ export class Router { partialState = {}; let combined = {...currentState, ...partialState}; - // prevent: Uncaught TypeError: Expected "component" to match "[^\/#\?]+?", but got "" - if (combined.component === '') { - combined.component = 'root'; + try { + return generateUrls(this.router)(this.routeName, combined); + } catch { + // XXX: In case we have partial state this will fail, just return the old path + return location.pathname; } - - return generateUrls(this.router)(this.routeName, combined); } dispatchLocationChanged(referrerUrl = "") { diff --git a/packages/app-shell/test/unit.js b/packages/app-shell/test/unit.js index ba047aeb724c82eea5f291d1f2d17e5da3ca275c..6943d1c2a038b210326ea9a20714e9dd663e3671 100644 --- a/packages/app-shell/test/unit.js +++ b/packages/app-shell/test/unit.js @@ -19,6 +19,7 @@ suite('router', () => { routeName: 'foo', getState: () => { return {}; }, setState: (state) => { }, + getDefaultState: () => { return {}; }, }); router.setStateFromCurrentLocation();