From b1b8b9583bf530ad5ce33f70611d96ee1ba8ccee Mon Sep 17 00:00:00 2001 From: Noel De Martin Date: Mon, 4 Dec 2023 17:01:05 +0100 Subject: [PATCH] MOBILE-3947 core: Fix circular routes --- src/app/app-routing.module.ts | 12 ++++- .../mainmenu/mainmenu-tab-routing.module.ts | 54 ++++++++++++++++--- 2 files changed, 58 insertions(+), 8 deletions(-) diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index b66bd26b1..869d3af27 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -27,6 +27,8 @@ import { import { CoreArray } from '@singletons/array'; +const modulesRoutes: WeakMap, ModuleRoutes> = new WeakMap(); + /** * Build app routes. * @@ -175,6 +177,10 @@ export function conditionalRoutes(routes: Routes, condition: () => boolean): Rou * @returns Routes. */ export function resolveModuleRoutes(injector: Injector, token: InjectionToken): ModuleRoutes { + if (modulesRoutes.has(token)) { + return modulesRoutes.get(token) as ModuleRoutes; + } + const configs = injector.get(token, []); const routes = configs.map(config => { if (Array.isArray(config)) { @@ -190,10 +196,14 @@ export function resolveModuleRoutes(injector: Injector, token: InjectionToken r.children)), siblings: CoreArray.flatten(routes.map(r => r.siblings)), }; + + modulesRoutes.set(token, moduleRoutes); + + return moduleRoutes; } export const APP_ROUTES = new InjectionToken('APP_ROUTES'); diff --git a/src/core/features/mainmenu/mainmenu-tab-routing.module.ts b/src/core/features/mainmenu/mainmenu-tab-routing.module.ts index 1e58919a7..6218138f1 100644 --- a/src/core/features/mainmenu/mainmenu-tab-routing.module.ts +++ b/src/core/features/mainmenu/mainmenu-tab-routing.module.ts @@ -18,24 +18,64 @@ import { Route, Routes } from '@angular/router'; import { ModuleRoutesConfig, resolveModuleRoutes } from '@/app/app-routing.module'; const MAIN_MENU_TAB_ROUTES = new InjectionToken('MAIN_MENU_TAB_ROUTES'); +const modulesPaths: Record> = {}; + +/** + * Get the name of the module the injector belongs to. + * + * @param injector Injector. + * @returns Injector module name. + */ +function getInjectorModule(injector: Injector): string | null { + if (!('source' in injector) || typeof injector.source !== 'string') { + return null; + } + + // Get module name from R3Injector source. + // See https://github.com/angular/angular/blob/16.2.0/packages/core/src/di/r3_injector.ts#L161C8 + return injector.source; +} + +/** + * Get module paths. + * + * @param injector Injector. + * @returns Module paths. + */ +function getModulePaths(injector: Injector): Set | null { + const module = getInjectorModule(injector); + + if (!module) { + return null; + } + + return modulesPaths[module] ??= new Set(); +} /** * Build module routes. * * @param injector Injector. + * @param mainRoute Main route. * @returns Routes. */ export function buildTabMainRoutes(injector: Injector, mainRoute: Route): Routes { + const path = mainRoute.path ?? ''; + const modulePaths = getModulePaths(injector); + const isRootRoute = modulePaths && !modulePaths.has(path); const routes = resolveModuleRoutes(injector, MAIN_MENU_TAB_ROUTES); - mainRoute.path = mainRoute.path || ''; - mainRoute.children = mainRoute.children || []; - mainRoute.children = mainRoute.children.concat(routes.children); + mainRoute.path = path; + modulePaths?.add(path); - return [ - mainRoute, - ...routes.siblings, - ]; + if (isRootRoute && !('redirectTo' in mainRoute)) { + mainRoute.children = mainRoute.children || []; + mainRoute.children = mainRoute.children.concat(routes.children); + } + + return isRootRoute + ? [mainRoute, ...routes.siblings] + : [mainRoute]; } @NgModule()