From c40b0ede111b37a110625b4355ee803c3302654f Mon Sep 17 00:00:00 2001 From: Jakob Rosenberg Date: Mon, 25 Mar 2024 15:45:21 +0100 Subject: [PATCH] fix: back & forward didn't track history correctly --- lib/runtime/Route/Route.js | 5 +++++ lib/runtime/Router/Router.js | 37 ++++++++++++++++++++++++++---------- 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/lib/runtime/Route/Route.js b/lib/runtime/Route/Route.js index cbf7f5f7..8c559392 100644 --- a/lib/runtime/Route/Route.js +++ b/lib/runtime/Route/Route.js @@ -25,6 +25,11 @@ export class Route { redirect: null, } + /** @type {Route} */ + prevRoute + /** @type {Route} */ + nextRoute + /** * @param {Router} router * @param {string} url diff --git a/lib/runtime/Router/Router.js b/lib/runtime/Router/Router.js index c3bdd7f0..02da456f 100644 --- a/lib/runtime/Router/Router.js +++ b/lib/runtime/Router/Router.js @@ -316,12 +316,12 @@ export class Router { // fix null state state = state || {} - const oldRoute = this.history.get(state.id) + const stackedRoute = this.history.get(state.id) - if (oldRoute?.meta.history) { - oldRoute.mode = 'popState' - oldRoute.state.cached = true - this.setActiveRoute(oldRoute) + if (stackedRoute?.meta.history) { + stackedRoute.mode = 'popState' + stackedRoute.state.cached = true + this.setActiveRoute(stackedRoute, null) return true } @@ -356,7 +356,7 @@ export class Router { // pending route could have changed while awaiting route.loadRoute() above if (this.pendingRoute.get() === route) this.pendingRoute.set(null) - if (didLoadRoute) this.setActiveRoute(route) + if (didLoadRoute) this.setActiveRoute(route, stackedRoute) // TODO Wait a tick for component rendering. There's probably be a better way to handle this. await new Promise(resolve => setTimeout(resolve)) @@ -365,7 +365,12 @@ export class Router { } } - setActiveRoute(route) { + /** + * + * @param {Route} route + * @param {Route} stackedRoute the route that was stacked in history with the same id + */ + setActiveRoute(route, stackedRoute) { // the route made it through all pretasks, lets set it to active this.log.debug('set active route', this) // ROUTIFY-DEV-ONLY @@ -375,6 +380,14 @@ export class Router { // lastRoute can't be the last entry in history, since we could be navigating back this.lastRoute = this.activeRoute.get() + + if (route.mode !== 'popState' && this.lastRoute) { + this.lastRoute.nextRoute = route + route.prevRoute = this.lastRoute + } else if (stackedRoute) { + route.nextRoute = stackedRoute.nextRoute + route.prevRoute = stackedRoute.prevRoute + } this.activeRoute.set(route) this.afterUrlChange.run({ @@ -423,9 +436,13 @@ export class Router { this.go(1) } go(count) { - const history = [...this.history.values()] - const index = history.findIndex(r => r === this.activeRoute.get()) - const newRoute = history[index + count] + const prop = count > 0 ? 'nextRoute' : 'prevRoute' + let newRoute = this.activeRoute.get() + while (count) { + newRoute = newRoute[prop] + count += count > 0 ? -1 : 1 + } + if (!newRoute) return this._setUrl(newRoute.url, 'popState', false, newRoute.state) } }