From 0819947072610be619ee9045f4c741982a5e617a Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Fri, 11 Dec 2020 13:14:34 +0100 Subject: [PATCH] MOBILE-3592 core: Implement new service CoreNavHelper --- src/core/directives/user-link.ts | 12 +- .../classes/module-list-handler.ts | 4 +- .../pages/choose-site/choose-site.ts | 4 +- .../services/contentlinks-helper.ts | 54 +-- .../features/course/services/course-helper.ts | 4 +- .../pages/change-password/change-password.ts | 3 +- .../login/pages/credentials/credentials.ts | 3 +- src/core/features/login/pages/init/init.ts | 7 +- .../login/pages/reconnect/reconnect.ts | 3 +- .../login/pages/site-policy/site-policy.ts | 3 +- src/core/features/login/pages/site/site.ts | 3 +- src/core/features/login/pages/sites/sites.ts | 3 +- .../features/login/services/login-helper.ts | 182 +-------- src/core/features/mainmenu/pages/menu/menu.ts | 7 +- .../sitehome/services/handlers/index-link.ts | 4 +- .../tag/services/handlers/index.link.ts | 8 +- .../tag/services/handlers/search.link.ts | 4 +- .../user/services/handlers/profile-link.ts | 4 +- src/core/services/app.ts | 41 +- src/core/services/nav-helper.ts | 363 ++++++++++++++++++ 20 files changed, 442 insertions(+), 274 deletions(-) create mode 100644 src/core/services/nav-helper.ts diff --git a/src/core/directives/user-link.ts b/src/core/directives/user-link.ts index f731306a9..3099ae77e 100644 --- a/src/core/directives/user-link.ts +++ b/src/core/directives/user-link.ts @@ -15,6 +15,7 @@ import { Directive, Input, OnInit, ElementRef } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { NavController } from '@ionic/angular'; +import { CoreNavHelper } from '@services/nav-helper'; import { CoreObject } from '@singletons/object'; @@ -53,13 +54,10 @@ export class CoreUserLinkDirective implements OnInit { event.stopPropagation(); // @todo If this directive is inside a split view, use the split view's master nav. - this.navCtrl.navigateForward(['user'], { - relativeTo: this.route, - queryParams: CoreObject.removeUndefined({ - userId: this.userId, - courseId: this.courseId, - }), - }); + CoreNavHelper.instance.goInCurrentMainMenuTab('user', CoreObject.removeUndefined({ + userId: this.userId, + courseId: this.courseId, + })); }); } diff --git a/src/core/features/contentlinks/classes/module-list-handler.ts b/src/core/features/contentlinks/classes/module-list-handler.ts index ecb929412..e6e2d663e 100644 --- a/src/core/features/contentlinks/classes/module-list-handler.ts +++ b/src/core/features/contentlinks/classes/module-list-handler.ts @@ -12,11 +12,11 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { CoreContentLinksHelper } from '../services/contentlinks-helper'; import { CoreContentLinksHandlerBase } from './base-handler'; import { Translate } from '@singletons'; import { Params } from '@angular/router'; import { CoreContentLinksAction } from '../services/contentlinks-delegate'; +import { CoreNavHelper } from '@services/nav-helper'; /** * Handler to handle URLs pointing to a list of a certain type of modules. @@ -65,7 +65,7 @@ export class CoreContentLinksModuleListHandler extends CoreContentLinksHandlerBa title: this.title || Translate.instance.instant('addon.mod_' + this.modName + '.modulenameplural'), }; - CoreContentLinksHelper.instance.goInSite('CoreCourseListModTypePage @todo', stateParams, siteId); + CoreNavHelper.instance.goInSite('CoreCourseListModTypePage @todo', stateParams, siteId); }, }]; } diff --git a/src/core/features/contentlinks/pages/choose-site/choose-site.ts b/src/core/features/contentlinks/pages/choose-site/choose-site.ts index 818170a0b..376de7f04 100644 --- a/src/core/features/contentlinks/pages/choose-site/choose-site.ts +++ b/src/core/features/contentlinks/pages/choose-site/choose-site.ts @@ -17,11 +17,11 @@ import { NavController } from '@ionic/angular'; import { CoreSiteBasicInfo, CoreSites } from '@services/sites'; import { CoreDomUtils } from '@services/utils/dom'; import { Translate } from '@singletons'; -import { CoreLoginHelper } from '@features/login/services/login-helper'; import { CoreContentLinksAction } from '../../services/contentlinks-delegate'; import { CoreContentLinksHelper } from '../../services/contentlinks-helper'; import { ActivatedRoute } from '@angular/router'; import { CoreError } from '@classes/errors/error'; +import { CoreNavHelper } from '@services/nav-helper'; /** * Page to display the list of sites to choose one to perform a content link action. @@ -102,7 +102,7 @@ export class CoreContentLinksChooseSitePage implements OnInit { */ siteClicked(siteId: string): void { if (this.isRootURL) { - CoreLoginHelper.instance.redirect('', {}, siteId); + CoreNavHelper.instance.openInSiteMainMenu('', {}, siteId); } else if (this.action) { this.action.action(siteId); } diff --git a/src/core/features/contentlinks/services/contentlinks-helper.ts b/src/core/features/contentlinks/services/contentlinks-helper.ts index 1da43ad0a..75631efce 100644 --- a/src/core/features/contentlinks/services/contentlinks-helper.ts +++ b/src/core/features/contentlinks/services/contentlinks-helper.ts @@ -16,13 +16,11 @@ import { Injectable } from '@angular/core'; import { NavController } from '@ionic/angular'; import { CoreSites } from '@services/sites'; import { CoreDomUtils } from '@services/utils/dom'; -import { CoreUtils } from '@services/utils/utils'; -import { CoreLoginHelper } from '@features/login/services/login-helper'; import { CoreContentLinksDelegate, CoreContentLinksAction } from './contentlinks-delegate'; import { CoreSite } from '@classes/site'; -import { CoreMainMenu } from '@features/mainmenu/services/mainmenu'; -import { makeSingleton, NgZone, Translate } from '@singletons'; +import { makeSingleton, Translate } from '@singletons'; import { Params } from '@angular/router'; +import { CoreNavHelper } from '@services/nav-helper'; /** * Service that provides some features regarding content links. @@ -94,50 +92,10 @@ export class CoreContentLinksHelperProvider { * @param siteId Site ID. If not defined, current site. * @param checkMenu If true, check if the root page of a main menu tab. Only the page name will be checked. * @return Promise resolved when done. + * @deprecated since 3.9.5. Use CoreNavHelperService.goInSite instead. */ - goInSite( - pageName: string, - pageParams: Params, - siteId?: string, - checkMenu?: boolean, - ): Promise { - siteId = siteId || CoreSites.instance.getCurrentSiteId(); - - const deferred = CoreUtils.instance.promiseDefer(); - - // Execute the code in the Angular zone, so change detection doesn't stop working. - NgZone.instance.run(async () => { - try { - if (siteId == CoreSites.instance.getCurrentSiteId()) { - if (checkMenu) { - let isInMenu = false; - // Check if the page is in the main menu. - try { - isInMenu = await CoreMainMenu.instance.isCurrentMainMenuHandler(pageName); - } catch { - isInMenu = false; - } - - if (isInMenu) { - // Just select the tab. @todo test. - CoreLoginHelper.instance.loadPageInMainMenu(pageName, pageParams); - } else { - await this.navCtrl.navigateForward(pageName, { queryParams: pageParams }); - } - } else { - await this.navCtrl.navigateForward(pageName, { queryParams: pageParams }); - } - } else { - await CoreLoginHelper.instance.redirect(pageName, pageParams, siteId); - } - - deferred.resolve(); - } catch (error) { - deferred.reject(error); - } - }); - - return deferred.promise; + goInSite(pageName: string, pageParams: Params, siteId?: string, checkMenu?: boolean): Promise { + return CoreNavHelper.instance.goInSite(pageName, pageParams, siteId, checkMenu); } /** @@ -234,7 +192,7 @@ export class CoreContentLinksHelperProvider { } } else { // Login in the site. - return CoreLoginHelper.instance.redirect('', {}, site.getId()); + return CoreNavHelper.instance.openInSiteMainMenu('', {}, site.getId()); } } diff --git a/src/core/features/course/services/course-helper.ts b/src/core/features/course/services/course-helper.ts index b581aa167..81f85e2cb 100644 --- a/src/core/features/course/services/course-helper.ts +++ b/src/core/features/course/services/course-helper.ts @@ -32,9 +32,9 @@ import { } from '@features/courses/services/courses'; import { CoreEnrolledCourseDataWithExtraInfoAndOptions } from '@features/courses/services/courses-helper'; import { CoreArray } from '@singletons/array'; -import { CoreLoginHelper, CoreLoginHelperProvider } from '@features/login/services/login-helper'; import { CoreIonLoadingElement } from '@classes/ion-loading'; import { CoreCourseOffline } from './course-offline'; +import { CoreNavHelper, CoreNavHelperService } from '@services/nav-helper'; /** * Prefetch info of a module. @@ -938,7 +938,7 @@ export class CoreCourseHelperProvider { params = params || {}; Object.assign(params, { course: course }); - return CoreLoginHelper.instance.redirect(CoreLoginHelperProvider.OPEN_COURSE, params, siteId); + return CoreNavHelper.instance.openInSiteMainMenu(CoreNavHelperService.OPEN_COURSE, params, siteId); } } diff --git a/src/core/features/login/pages/change-password/change-password.ts b/src/core/features/login/pages/change-password/change-password.ts index a8e180e95..9872eb67a 100644 --- a/src/core/features/login/pages/change-password/change-password.ts +++ b/src/core/features/login/pages/change-password/change-password.ts @@ -18,6 +18,7 @@ import { CoreSites } from '@services/sites'; import { CoreDomUtils } from '@services/utils/dom'; import { CoreLoginHelper } from '@features/login/services/login-helper'; import { Translate } from '@singletons'; +import { CoreNavHelper } from '@services/nav-helper'; /** * Page that shows instructions to change the password. @@ -62,7 +63,7 @@ export class CoreLoginChangePasswordPage { * Login the user. */ login(): void { - CoreLoginHelper.instance.goToSiteInitialPage(); + CoreNavHelper.instance.goToSiteInitialPage(); this.changingPassword = false; } diff --git a/src/core/features/login/pages/credentials/credentials.ts b/src/core/features/login/pages/credentials/credentials.ts index 2e142adbf..118360ee3 100644 --- a/src/core/features/login/pages/credentials/credentials.ts +++ b/src/core/features/login/pages/credentials/credentials.ts @@ -26,6 +26,7 @@ import { CoreConstants } from '@/core/constants'; import { Translate } from '@singletons'; import { CoreSiteIdentityProvider, CoreSitePublicConfigResponse } from '@classes/site'; import { CoreEvents } from '@singletons/events'; +import { CoreNavHelper } from '@services/nav-helper'; /** * Page to enter the user credentials. @@ -244,7 +245,7 @@ export class CoreLoginCredentialsPage implements OnInit, OnDestroy { this.siteId = id; - await CoreLoginHelper.instance.goToSiteInitialPage({ urlToOpen: this.urlToOpen }); + await CoreNavHelper.instance.goToSiteInitialPage({ urlToOpen: this.urlToOpen }); } catch (error) { CoreLoginHelper.instance.treatUserTokenError(siteUrl, error, username, password); diff --git a/src/core/features/login/pages/init/init.ts b/src/core/features/login/pages/init/init.ts index a1f726fac..97f89a85a 100644 --- a/src/core/features/login/pages/init/init.ts +++ b/src/core/features/login/pages/init/init.ts @@ -20,6 +20,7 @@ import { ApplicationInit, SplashScreen } from '@singletons'; import { CoreConstants } from '@/core/constants'; import { CoreSites } from '@services/sites'; import { CoreLoginHelper } from '@features/login/services/login-helper'; +import { CoreNavHelper } from '@services/nav-helper'; /** * Page that displays a "splash screen" while the app is being initialized. @@ -79,7 +80,7 @@ export class CoreLoginInitPage implements OnInit { return; } - return CoreLoginHelper.instance.goToSiteInitialPage({ + return CoreNavHelper.instance.goToSiteInitialPage({ redirectPage: redirectData.page, redirectParams: redirectData.params, }); @@ -89,7 +90,7 @@ export class CoreLoginInitPage implements OnInit { } } else if (redirectData.page) { // No site to load, open the page. - return CoreLoginHelper.instance.goToNoSitePage(redirectData.page, redirectData.params); + return CoreNavHelper.instance.goToNoSitePage(redirectData.page, redirectData.params); } } @@ -109,7 +110,7 @@ export class CoreLoginInitPage implements OnInit { return this.loadPage(); } - return CoreLoginHelper.instance.goToSiteInitialPage(); + return CoreNavHelper.instance.goToSiteInitialPage(); } await this.navCtrl.navigateRoot('/login/sites'); diff --git a/src/core/features/login/pages/reconnect/reconnect.ts b/src/core/features/login/pages/reconnect/reconnect.ts index eee6daf88..729bcd50b 100644 --- a/src/core/features/login/pages/reconnect/reconnect.ts +++ b/src/core/features/login/pages/reconnect/reconnect.ts @@ -25,6 +25,7 @@ import { CoreLoginHelper } from '@features/login/services/login-helper'; import { CoreSiteIdentityProvider, CoreSitePublicConfigResponse } from '@classes/site'; import { CoreEvents } from '@singletons/events'; import { CoreError } from '@classes/errors/error'; +import { CoreNavHelper } from '@services/nav-helper'; /** * Page to enter the user password to reconnect to a site. @@ -206,7 +207,7 @@ export class CoreLoginReconnectPage implements OnInit, OnDestroy { this.credForm.controls['password'].reset(); // Go to the site initial page. - await CoreLoginHelper.instance.goToSiteInitialPage({ + await CoreNavHelper.instance.goToSiteInitialPage({ redirectPage: this.page, redirectParams: this.pageParams, }); diff --git a/src/core/features/login/pages/site-policy/site-policy.ts b/src/core/features/login/pages/site-policy/site-policy.ts index fb6e31988..b38591b98 100644 --- a/src/core/features/login/pages/site-policy/site-policy.ts +++ b/src/core/features/login/pages/site-policy/site-policy.ts @@ -22,6 +22,7 @@ import { CoreUtils } from '@services/utils/utils'; import { CoreMimetypeUtils } from '@services/utils/mimetype'; import { CoreLoginHelper } from '@features/login/services/login-helper'; import { CoreSite } from '@classes/site'; +import { CoreNavHelper } from '@services/nav-helper'; /** * Page to accept a site policy. @@ -128,7 +129,7 @@ export class CoreLoginSitePolicyPage implements OnInit { // Invalidate cache since some WS don't return error if site policy is not accepted. await CoreUtils.instance.ignoreErrors(this.currentSite!.invalidateWsCache()); - await CoreLoginHelper.instance.goToSiteInitialPage(); + await CoreNavHelper.instance.goToSiteInitialPage(); } catch (error) { CoreDomUtils.instance.showErrorModalDefault(error, 'Error accepting site policy.'); } finally { diff --git a/src/core/features/login/pages/site/site.ts b/src/core/features/login/pages/site/site.ts index 5abfb1859..7d60e9871 100644 --- a/src/core/features/login/pages/site/site.ts +++ b/src/core/features/login/pages/site/site.ts @@ -31,6 +31,7 @@ import { CoreUrl } from '@singletons/url'; import { CoreUrlUtils } from '@services/utils/url'; import { CoreLoginSiteHelpComponent } from '@features/login/components/site-help/site-help'; import { CoreLoginSiteOnboardingComponent } from '@features/login/components/site-onboarding/site-onboarding'; +import { CoreNavHelper } from '@services/nav-helper'; /** * Page that displays a "splash screen" while the app is being initialized. @@ -328,7 +329,7 @@ export class CoreLoginSitePage implements OnInit { CoreDomUtils.instance.triggerFormSubmittedEvent(this.formElement, true); - return CoreLoginHelper.instance.goToSiteInitialPage(); + return CoreNavHelper.instance.goToSiteInitialPage(); } catch (error) { CoreLoginHelper.instance.treatUserTokenError(siteData.url, error, siteData.username, siteData.password); diff --git a/src/core/features/login/pages/sites/sites.ts b/src/core/features/login/pages/sites/sites.ts index 99de3b67b..276bb6a94 100644 --- a/src/core/features/login/pages/sites/sites.ts +++ b/src/core/features/login/pages/sites/sites.ts @@ -19,6 +19,7 @@ import { Component, OnInit } from '@angular/core'; import { CoreSiteBasicInfo, CoreSites } from '@services/sites'; import { CoreLogger } from '@singletons/logger'; import { CoreLoginHelper } from '@features/login/services/login-helper'; +import { CoreNavHelper } from '@services/nav-helper'; /** * Page that displays a "splash screen" while the app is being initialized. @@ -124,7 +125,7 @@ export class CoreLoginSitesPage implements OnInit { const loggedIn = await CoreSites.instance.loadSite(siteId); if (loggedIn) { - return CoreLoginHelper.instance.goToSiteInitialPage(); + return CoreNavHelper.instance.goToSiteInitialPage(); } } catch (error) { this.logger.error('Error loading site ' + siteId, error); diff --git a/src/core/features/login/services/login-helper.ts b/src/core/features/login/services/login-helper.ts index fbb3be5e1..1b50a1c7e 100644 --- a/src/core/features/login/services/login-helper.ts +++ b/src/core/features/login/services/login-helper.ts @@ -13,7 +13,6 @@ // limitations under the License. import { Injectable } from '@angular/core'; -import { Location } from '@angular/common'; import { Params } from '@angular/router'; import { NavController } from '@ionic/angular'; import { Md5 } from 'ts-md5/dist/md5'; @@ -34,8 +33,8 @@ import { CoreWSError } from '@classes/errors/wserror'; import { makeSingleton, Translate } from '@singletons'; import { CoreLogger } from '@singletons/logger'; import { CoreUrl } from '@singletons/url'; -import { NavigationOptions } from '@ionic/angular/providers/nav-controller'; import { CoreObject } from '@singletons/object'; +import { CoreNavHelper, CoreNavHelperOpenMainMenuOptions, CoreNavHelperService } from '@services/nav-helper'; /** * Helper provider that provides some common features regarding authentication. @@ -43,7 +42,7 @@ import { CoreObject } from '@singletons/object'; @Injectable({ providedIn: 'root' }) export class CoreLoginHelperProvider { - static readonly OPEN_COURSE = 'open_course'; + static readonly OPEN_COURSE = CoreNavHelperService.OPEN_COURSE; // @deprecated since 3.9.5. static readonly ONBOARDING_DONE = 'onboarding_done'; static readonly FAQ_URL_IMAGE_HTML = ''; static readonly FAQ_QRCODE_IMAGE_HTML = ''; @@ -51,24 +50,13 @@ export class CoreLoginHelperProvider { protected logger: CoreLogger; protected isSSOConfirmShown = false; protected isOpenEditAlertShown = false; - protected pageToLoad?: {page: string; params?: Params; time: number}; // Page to load once main menu is opened. protected isOpeningReconnect = false; waitingForBrowser = false; constructor( - protected location: Location, protected navCtrl: NavController, ) { this.logger = CoreLogger.getInstance('CoreLoginHelper'); - - CoreEvents.on(CoreEvents.MAIN_MENU_OPEN, () => { - /* If there is any page pending to be opened, do it now. Don't open pages stored more than 5 seconds ago, probably - the function to open the page was called when it shouldn't. */ - if (this.pageToLoad && Date.now() - this.pageToLoad.time < 5000) { - this.loadPageInMainMenu(this.pageToLoad.page, this.pageToLoad.params); - delete this.pageToLoad; - } - }); } /** @@ -123,7 +111,7 @@ export class CoreLoginHelperProvider { */ checkLogout(): void { const currentSite = CoreSites.instance.getCurrentSite(); - const currentPage = CoreApp.instance.getCurrentPage(); + const currentPage = CoreNavHelper.instance.getCurrentPage(); if (!CoreApp.instance.isSSOAuthenticationOngoing() && currentSite?.isLoggedOut() && currentPage == '/login/reconnect') { // User must reauthenticate but he closed the InAppBrowser without doing so, logout him. @@ -448,39 +436,10 @@ export class CoreLoginHelperProvider { * @param page Page to open. * @param params Params of the page. * @return Promise resolved when done. + * @deprecated since 3.9.5. Use CoreNavHelperService.goToNoSitePage instead. */ - async goToNoSitePage(page: string, params?: Params): Promise { - const currentPage = CoreApp.instance.getCurrentPage(); - - if (currentPage == page) { - // Already at page, nothing to do. - } else if (page == '/login/sites') { - // Just open the page as root. - await this.navCtrl.navigateRoot(page, { queryParams: params }); - } else if (page == '/login/credentials' && currentPage == '/login/site') { - // Just open the new page to keep the navigation history. - await this.navCtrl.navigateForward(page, { queryParams: params }); - } else { - // Check if there is any site stored. - const hasSites = await CoreSites.instance.hasSites(); - - if (!hasSites) { - // There are sites stored, open sites page first to be able to go back. - await this.navCtrl.navigateRoot('/login/sites'); - - await this.navCtrl.navigateForward(page, { queryParams: params }); - } else { - if (page != '/login/site') { - // Open the new site page to be able to go back. - await this.navCtrl.navigateRoot('/login/site'); - - await this.navCtrl.navigateForward(page, { queryParams: params }); - } else { - // Just open the page as root. - await this.navCtrl.navigateRoot(page, { queryParams: params }); - } - } - } + goToNoSitePage(page: string, params?: Params): Promise { + return CoreNavHelper.instance.goToNoSitePage(page, params); } /** @@ -488,9 +447,10 @@ export class CoreLoginHelperProvider { * * @param options Options. * @return Promise resolved when done. + * @deprecated since 3.9.5. Use CoreNavHelperService.goToSiteInitialPage instead. */ - goToSiteInitialPage(options?: OpenMainMenuOptions): Promise { - return this.openMainMenu(options); + goToSiteInitialPage(options?: CoreNavHelperOpenMainMenuOptions): Promise { + return CoreNavHelper.instance.goToSiteInitialPage(options); } /** @@ -641,97 +601,15 @@ export class CoreLoginHelperProvider { return code == CoreConstants.LOGIN_SSO_CODE || code == CoreConstants.LOGIN_SSO_INAPP_CODE; } - /** - * Load a site and load a certain page in that site. - * - * @param siteId Site to load. - * @param page Name of the page to load. - * @param params Params to pass to the page. - * @return Promise resolved when done. - */ - protected async loadSiteAndPage(siteId: string, page: string, params?: Params): Promise { - if (siteId == CoreConstants.NO_SITE_ID) { - // Page doesn't belong to a site, just load the page. - await this.navCtrl.navigateRoot(page, params); - - return; - } - - const modal = await CoreDomUtils.instance.showModalLoading(); - - try { - const loggedIn = await CoreSites.instance.loadSite(siteId, page, params); - - if (!loggedIn) { - return; - } - - await this.openMainMenu({ - redirectPage: page, - redirectParams: params, - }); - } catch (error) { - // Site doesn't exist. - await this.navCtrl.navigateRoot('/login/sites'); - } finally { - modal.dismiss(); - } - } - /** * Load a certain page in the main menu page. * * @param page Name of the page to load. * @param params Params to pass to the page. + * @deprecated since 3.9.5. Use CoreNavHelperService.loadPageInMainMenu instead. */ loadPageInMainMenu(page: string, params?: Params): void { - if (!CoreApp.instance.isMainMenuOpen()) { - // Main menu not open. Store the page to be loaded later. - this.pageToLoad = { - page: page, - params: params, - time: Date.now(), - }; - - return; - } - - if (page == CoreLoginHelperProvider.OPEN_COURSE) { - // @todo Use the openCourse function. - } else { - CoreEvents.trigger(CoreEvents.LOAD_PAGE_MAIN_MENU, { redirectPage: page, redirectParams: params }); - } - } - - /** - * Open the main menu, loading a certain page. - * - * @param options Options. - * @return Promise resolved when done. - */ - protected async openMainMenu(options?: OpenMainMenuOptions): Promise { - - // Due to DeepLinker, we need to remove the path from the URL before going to main menu. - // IonTabs checks the URL to determine which path to load for deep linking, so we clear the URL. - // @todo this.location.replaceState(''); - - if (options?.redirectPage == CoreLoginHelperProvider.OPEN_COURSE) { - // Load the main menu first, and then open the course. - try { - await this.navCtrl.navigateRoot('/'); - } finally { - // @todo: Open course. - } - } else { - // Open the main menu. - const queryParams: Params = Object.assign({}, options); - delete queryParams.navigationOptions; - - await this.navCtrl.navigateRoot('/', { - queryParams, - ...options?.navigationOptions, - }); - } + CoreNavHelper.instance.loadPageInMainMenu(page, params); } /** @@ -889,7 +767,7 @@ export class CoreLoginHelperProvider { return; // Site that triggered the event is not current site. } - const currentPage = CoreApp.instance.getCurrentPage(); + const currentPage = CoreNavHelper.instance.getCurrentPage(); // If current page is already change password, stop. if (currentPage == '/login/changepassword') { @@ -948,31 +826,14 @@ export class CoreLoginHelperProvider { /** * Redirect to a new page, setting it as the root page and loading the right site if needed. * - * @param page Name of the page to load. Special cases: OPEN_COURSE (to open course page). + * @param page Name of the page to load. Special cases: CoreNavHelperService.OPEN_COURSE (to open course page). * @param params Params to pass to the page. * @param siteId Site to load. If not defined, current site. * @return Promise resolved when done. + * @deprecated since 3.9.5. Use CoreNavHelperService.openInSiteMainMenu instead. */ - async redirect(page: string, params?: Params, siteId?: string): Promise { - siteId = siteId || CoreSites.instance.getCurrentSiteId(); - - if (CoreSites.instance.isLoggedIn()) { - if (siteId && siteId != CoreSites.instance.getCurrentSiteId()) { - // Target page belongs to a different site. Change site. - // @todo: Check site plugins. - await CoreSites.instance.logout(); - - await this.loadSiteAndPage(siteId, page, params); - } else { - this.loadPageInMainMenu(page, params); - } - } else { - if (siteId) { - await this.loadSiteAndPage(siteId, page, params); - } else { - await this.navCtrl.navigateRoot('/login/sites'); - } - } + redirect(page: string, params?: Params, siteId?: string): Promise { + return CoreNavHelper.instance.openInSiteMainMenu(page, params, siteId); } /** @@ -1098,7 +959,7 @@ export class CoreLoginHelperProvider { const info = currentSite.getInfo(); if (typeof info != 'undefined' && typeof info.username != 'undefined' && !this.isOpeningReconnect) { // If current page is already reconnect, stop. - if (CoreApp.instance.getCurrentPage() == '/login/reconnect') { + if (CoreNavHelper.instance.getCurrentPage() == '/login/reconnect') { return; } @@ -1266,7 +1127,7 @@ export class CoreLoginHelperProvider { } // If current page is already site policy, stop. - if (CoreApp.instance.getCurrentPage() == '/login/sitepolicy') { + if (CoreNavHelper.instance.getCurrentPage() == '/login/sitepolicy') { return; } @@ -1474,10 +1335,3 @@ type StoredLoginLaunchData = { pageParams: Params; ssoUrlParams: CoreUrlParams; }; - -type OpenMainMenuOptions = { - redirectPage?: string; // Route of the page to open in main menu. If not defined, default tab will be selected. - redirectParams?: Params; // Params to pass to the selected tab if any. - urlToOpen?: string; // URL to open once the main menu is loaded. - navigationOptions?: NavigationOptions; // Navigation options. -}; diff --git a/src/core/features/mainmenu/pages/menu/menu.ts b/src/core/features/mainmenu/pages/menu/menu.ts index 5d58bd6d6..9e99e239e 100644 --- a/src/core/features/mainmenu/pages/menu/menu.ts +++ b/src/core/features/mainmenu/pages/menu/menu.ts @@ -25,6 +25,7 @@ import { CoreMainMenu } from '../../services/mainmenu'; import { CoreMainMenuDelegate, CoreMainMenuHandlerToDisplay } from '../../services/mainmenu-delegate'; import { CoreDomUtils } from '@services/utils/dom'; import { Translate } from '@singletons'; +import { CoreNavHelper } from '@services/nav-helper'; /** * Page that displays the main menu of the app. @@ -60,7 +61,7 @@ export class CoreMainMenuPage implements OnInit, OnDestroy { protected changeDetector: ChangeDetectorRef, protected router: Router, ) { - this.mainMenuId = CoreApp.instance.getMainMenuId(); + this.mainMenuId = CoreNavHelper.instance.getMainMenuId(); } /** @@ -131,7 +132,7 @@ export class CoreMainMenuPage implements OnInit, OnDestroy { }); } - CoreApp.instance.setMainMenuOpen(this.mainMenuId, true); + CoreNavHelper.instance.setMainMenuOpen(this.mainMenuId, true); } /** @@ -226,7 +227,7 @@ export class CoreMainMenuPage implements OnInit, OnDestroy { this.subscription?.unsubscribe(); this.redirectObs?.off(); window.removeEventListener('resize', this.initHandlers.bind(this)); - CoreApp.instance.setMainMenuOpen(this.mainMenuId, false); + CoreNavHelper.instance.setMainMenuOpen(this.mainMenuId, false); this.keyboardObserver?.off(); } diff --git a/src/core/features/sitehome/services/handlers/index-link.ts b/src/core/features/sitehome/services/handlers/index-link.ts index 7faa9d8ee..567a0230a 100644 --- a/src/core/features/sitehome/services/handlers/index-link.ts +++ b/src/core/features/sitehome/services/handlers/index-link.ts @@ -16,10 +16,10 @@ import { Injectable } from '@angular/core'; import { Params } from '@angular/router'; import { CoreSites } from '@services/sites'; import { CoreContentLinksHandlerBase } from '@features/contentlinks/classes/base-handler'; -import { CoreContentLinksHelper } from '@features/contentlinks/services/contentlinks-helper'; import { CoreContentLinksAction } from '@features/contentlinks/services/contentlinks-delegate'; import { CoreSiteHome } from '../sitehome'; import { makeSingleton } from '@singletons'; +import { CoreNavHelper } from '@services/nav-helper'; /** * Handler to treat links to site home index. @@ -43,7 +43,7 @@ export class CoreSiteHomeIndexLinkHandlerService extends CoreContentLinksHandler getActions(): CoreContentLinksAction[] | Promise { return [{ action: (siteId: string): void => { - CoreContentLinksHelper.instance.goInSite('sitehome', [], siteId); + CoreNavHelper.instance.goInSite('sitehome', [], siteId); }, }]; } diff --git a/src/core/features/tag/services/handlers/index.link.ts b/src/core/features/tag/services/handlers/index.link.ts index 01bb95568..b4836cd73 100644 --- a/src/core/features/tag/services/handlers/index.link.ts +++ b/src/core/features/tag/services/handlers/index.link.ts @@ -16,7 +16,7 @@ import { Injectable } from '@angular/core'; import { Params } from '@angular/router'; import { CoreContentLinksHandlerBase } from '@features/contentlinks/classes/base-handler'; import { CoreContentLinksAction } from '@features/contentlinks/services/contentlinks-delegate'; -import { CoreContentLinksHelper } from '@features/contentlinks/services/contentlinks-helper'; +import { CoreNavHelper } from '@services/nav-helper'; import { makeSingleton } from '@singletons'; import { CoreTag } from '../tag'; @@ -57,11 +57,11 @@ export class CoreTagIndexLinkHandlerService extends CoreContentLinksHandlerBase }; if (!pageParams.tagId && (!pageParams.tagName || !pageParams.collectionId)) { - CoreContentLinksHelper.instance.goInSite('/main/tag/search', {}, siteId); + CoreNavHelper.instance.goInSite('/tag/search', {}, siteId); } else if (pageParams.areaId) { - CoreContentLinksHelper.instance.goInSite('/main/tag/index-area', pageParams, siteId); + CoreNavHelper.instance.goInSite('/tag/index-area', pageParams, siteId); } else { - CoreContentLinksHelper.instance.goInSite('/main/tag/index', pageParams, siteId); + CoreNavHelper.instance.goInSite('/tag/index', pageParams, siteId); } }, }]; diff --git a/src/core/features/tag/services/handlers/search.link.ts b/src/core/features/tag/services/handlers/search.link.ts index 610af58b8..382a09688 100644 --- a/src/core/features/tag/services/handlers/search.link.ts +++ b/src/core/features/tag/services/handlers/search.link.ts @@ -16,7 +16,7 @@ import { Injectable } from '@angular/core'; import { Params } from '@angular/router'; import { CoreContentLinksHandlerBase } from '@features/contentlinks/classes/base-handler'; import { CoreContentLinksAction } from '@features/contentlinks/services/contentlinks-delegate'; -import { CoreContentLinksHelper } from '@features/contentlinks/services/contentlinks-helper'; +import { CoreNavHelper } from '@services/nav-helper'; import { makeSingleton } from '@singletons'; import { CoreTag } from '../tag'; @@ -47,7 +47,7 @@ export class CoreTagSearchLinkHandlerService extends CoreContentLinksHandlerBase query: params.query || '', }; - CoreContentLinksHelper.instance.goInSite('/main/tag/search', pageParams, siteId); + CoreNavHelper.instance.goInSite('/tag/search', pageParams, siteId); }, }]; } diff --git a/src/core/features/user/services/handlers/profile-link.ts b/src/core/features/user/services/handlers/profile-link.ts index e1453224d..ca3f70c6f 100644 --- a/src/core/features/user/services/handlers/profile-link.ts +++ b/src/core/features/user/services/handlers/profile-link.ts @@ -17,7 +17,7 @@ import { Params } from '@angular/router'; import { CoreContentLinksHandlerBase } from '@features/contentlinks/classes/base-handler'; import { CoreContentLinksAction } from '@features/contentlinks/services/contentlinks-delegate'; -import { CoreContentLinksHelper } from '@features/contentlinks/services/contentlinks-helper'; +import { CoreNavHelper } from '@services/nav-helper'; import { makeSingleton } from '@singletons'; /** @@ -54,7 +54,7 @@ export class CoreUserProfileLinkHandlerService extends CoreContentLinksHandlerBa userId: parseInt(params.id, 10), }; - CoreContentLinksHelper.instance.goInSite('/user', pageParams, siteId); + CoreNavHelper.instance.goInSite('/user', pageParams, siteId); }, }]; } diff --git a/src/core/services/app.ts b/src/core/services/app.ts index 945b9dc4b..66fbc8e8d 100644 --- a/src/core/services/app.ts +++ b/src/core/services/app.ts @@ -13,19 +13,19 @@ // limitations under the License. import { Injectable } from '@angular/core'; -import { Params, Router } from '@angular/router'; +import { Params } from '@angular/router'; import { Connection } from '@ionic-native/network/ngx'; import { CoreDB } from '@services/db'; import { CoreEvents } from '@singletons/events'; import { CoreUtils, PromiseDefer } from '@services/utils/utils'; -import { CoreUrlUtils } from '@services/utils/url'; import { SQLiteDB, SQLiteDBTableSchema } from '@classes/sqlitedb'; import { makeSingleton, Keyboard, Network, StatusBar, Platform, Device } from '@singletons'; import { CoreLogger } from '@singletons/logger'; import { CoreColors } from '@singletons/colors'; import { DBNAME, SCHEMA_VERSIONS_TABLE_NAME, SCHEMA_VERSIONS_TABLE_SCHEMA, SchemaVersionsDBEntry } from '@services/database/app'; +import { CoreNavHelper } from './nav-helper'; /** * Object responsible of managing schema versions. @@ -58,15 +58,13 @@ export class CoreAppProvider { protected keyboardOpening = false; protected keyboardClosing = false; protected backActions: {callback: () => boolean; priority: number}[] = []; - protected mainMenuId = 0; - protected mainMenuOpen?: number; protected forceOffline = false; // Variables for DB. protected schemaVersionsManager: Promise; protected resolveSchemaVersionsManager!: (schemaVersionsManager: SchemaVersionsManager) => void; - constructor(protected router: Router) { + constructor() { this.schemaVersionsManager = new Promise(resolve => this.resolveSchemaVersionsManager = resolve); this.db = CoreDB.instance.getDB(DBNAME); this.logger = CoreLogger.getInstance('CoreAppProvider'); @@ -167,15 +165,6 @@ export class CoreAppProvider { schemaVersionsManager.set(schema.name, schema.version); } - /** - * Get current page route without params. - * - * @return Current page route. - */ - getCurrentPage(): string { - return CoreUrlUtils.instance.removeUrlParams(this.router.url); - } - /** * Get the application global database. * @@ -189,9 +178,10 @@ export class CoreAppProvider { * Get an ID for a main menu. * * @return Main menu ID. + * @deprecated since 3.9.5. Use CoreNavHelperService.getMainMenuId instead. */ getMainMenuId(): number { - return this.mainMenuId++; + return CoreNavHelper.instance.getMainMenuId(); } /** @@ -231,7 +221,7 @@ export class CoreAppProvider { * Checks if the app is running in a 64 bits desktop environment (not browser). * * @return false. - * @deprecated Desktop support has been removed. + * @deprecated since 3.9.5 Desktop support has been removed. */ is64Bits(): boolean { return false; @@ -250,7 +240,7 @@ export class CoreAppProvider { * Checks if the app is running in a desktop environment (not browser). * * @return false. - * @deprecated Desktop support has been removed. + * @deprecated since 3.9.5 Desktop support has been removed. */ isDesktop(): boolean { return false; @@ -296,7 +286,7 @@ export class CoreAppProvider { * Check if the app is running in a Linux environment. * * @return false. - * @deprecated Desktop support has been removed. + * @deprecated since 3.9.5 Desktop support has been removed. */ isLinux(): boolean { return false; @@ -306,7 +296,7 @@ export class CoreAppProvider { * Check if the app is running in a Mac OS environment. * * @return false. - * @deprecated Desktop support has been removed. + * @deprecated since 3.9.5 Desktop support has been removed. */ isMac(): boolean { return false; @@ -316,9 +306,10 @@ export class CoreAppProvider { * Check if the main menu is open. * * @return Whether the main menu is open. + * @deprecated since 3.9.5. Use CoreNavHelperService.isMainMenuOpen instead. */ isMainMenuOpen(): boolean { - return typeof this.mainMenuOpen != 'undefined'; + return CoreNavHelper.instance.isMainMenuOpen(); } /** @@ -389,7 +380,7 @@ export class CoreAppProvider { * Check if the app is running in a Windows environment. * * @return false. - * @deprecated Desktop support has been removed. + * @deprecated since 3.9.5 Desktop support has been removed. */ isWindows(): boolean { return false; @@ -459,14 +450,10 @@ export class CoreAppProvider { * * @param id Main menu ID. * @param open Whether it's open or not. + * @deprecated since 3.9.5. Use CoreNavHelperService.setMainMenuOpen instead. */ setMainMenuOpen(id: number, open: boolean): void { - if (open) { - this.mainMenuOpen = id; - CoreEvents.trigger(CoreEvents.MAIN_MENU_OPEN); - } else if (this.mainMenuOpen == id) { - delete this.mainMenuOpen; - } + CoreNavHelper.instance.setMainMenuOpen(id, open); } /** diff --git a/src/core/services/nav-helper.ts b/src/core/services/nav-helper.ts new file mode 100644 index 000000000..2a98bd871 --- /dev/null +++ b/src/core/services/nav-helper.ts @@ -0,0 +1,363 @@ +// (C) Copyright 2015 Moodle Pty Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { Injectable } from '@angular/core'; +import { Params, Router } from '@angular/router'; +import { CoreMainMenu } from '@features/mainmenu/services/mainmenu'; +import { NavController } from '@ionic/angular'; +import { NavigationOptions } from '@ionic/angular/providers/nav-controller'; + +import { makeSingleton } from '@singletons'; +import { CoreEvents } from '@singletons/events'; +import { CoreConstants } from '../constants'; +import { CoreSites } from './sites'; +import { CoreDomUtils } from './utils/dom'; +import { CoreTextUtils } from './utils/text'; +import { CoreUrlUtils } from './utils/url'; + +/** + * Provider to provide some helper functions regarding navigation. + */ +@Injectable({ providedIn: 'root' }) +export class CoreNavHelperService { + + static readonly OPEN_COURSE = 'open_course'; + + protected pageToLoad?: {page: string; params?: Params; time: number}; // Page to load once main menu is opened. + protected mainMenuOpen?: number; + protected mainMenuId = 0; + + constructor( + protected router: Router, + protected navCtrl: NavController, + ) { + CoreEvents.on(CoreEvents.MAIN_MENU_OPEN, () => { + /* If there is any page pending to be opened, do it now. Don't open pages stored more than 5 seconds ago, probably + the function to open the page was called when it shouldn't. */ + if (this.pageToLoad && Date.now() - this.pageToLoad.time < 5000) { + this.loadPageInMainMenu(this.pageToLoad.page, this.pageToLoad.params); + delete this.pageToLoad; + } + }); + } + + /** + * Get current page route without params. + * + * @return Current page route. + */ + getCurrentPage(): string { + return CoreUrlUtils.instance.removeUrlParams(this.router.url); + } + + /** + * Open a new page in the current main menu tab. + * + * @param page Page to open. + * @param pageParams Params to send to the page. + * @return Promise resolved when done. + */ + async goInCurrentMainMenuTab(page: string, pageParams: Params): Promise { + const currentPage = this.getCurrentPage(); + + const routeMatch = currentPage.match(/^\/main\/([^/]+)/); + if (!routeMatch || !routeMatch[0]) { + // Not in a tab. Stop. + return; + } + + let path = ''; + if (routeMatch[1] && page.match(new RegExp(`^/${routeMatch[1]}(/|$)`))) { + path = CoreTextUtils.instance.concatenatePaths('/main', page); + } else { + path = CoreTextUtils.instance.concatenatePaths(routeMatch[0], page); + } + + await this.navCtrl.navigateForward(path, { + queryParams: pageParams, + }); + } + + /** + * Goes to a certain page in a certain site. If the site is current site it will perform a regular navigation, + * otherwise it will load the other site and open the page in main menu. + * + * @param pageName Name of the page to go. + * @param pageParams Params to send to the page. + * @param siteId Site ID. If not defined, current site. + * @param checkMenu If true, check if the root page of a main menu tab. Only the page name will be checked. + * @return Promise resolved when done. + */ + async goInSite(pageName: string, pageParams: Params, siteId?: string, checkMenu?: boolean): Promise { + siteId = siteId || CoreSites.instance.getCurrentSiteId(); + + // @todo: When this function was in ContentLinksHelper, this code was inside NgZone. Check if it's needed. + + if (!CoreSites.instance.isLoggedIn() || siteId != CoreSites.instance.getCurrentSiteId()) { + await this.openInSiteMainMenu(pageName, pageParams, siteId); + + return; + } + + if (checkMenu) { + let isInMenu = false; + // Check if the page is in the main menu. + try { + isInMenu = await CoreMainMenu.instance.isCurrentMainMenuHandler(pageName); + } catch { + isInMenu = false; + } + + if (isInMenu) { + // Just select the tab. @todo test. + CoreNavHelper.instance.loadPageInMainMenu(pageName, pageParams); + + return; + } + } + + await this.goInCurrentMainMenuTab(pageName, pageParams); + } + + /** + * Get an ID for a main menu. + * + * @return Main menu ID. + */ + getMainMenuId(): number { + return this.mainMenuId++; + } + + /** + * Open a page that doesn't belong to any site. + * + * @param page Page to open. + * @param params Params of the page. + * @return Promise resolved when done. + */ + async goToNoSitePage(page: string, params?: Params): Promise { + const currentPage = this.getCurrentPage(); + + if (currentPage == page) { + // Already at page, nothing to do. + return; + } + + if (page == '/login/sites') { + // Just open the page as root. + await this.navCtrl.navigateRoot(page, { queryParams: params }); + + return; + } + + if (page == '/login/credentials' && currentPage == '/login/site') { + // Just open the new page to keep the navigation history. + await this.navCtrl.navigateForward(page, { queryParams: params }); + + return; + } + + // Check if there is any site stored. + const hasSites = await CoreSites.instance.hasSites(); + + if (!hasSites) { + // There are sites stored, open sites page first to be able to go back. + await this.navCtrl.navigateRoot('/login/sites'); + + await this.navCtrl.navigateForward(page, { queryParams: params }); + + return; + } + + if (page != '/login/site') { + // Open the new site page to be able to go back. + await this.navCtrl.navigateRoot('/login/site'); + + await this.navCtrl.navigateForward(page, { queryParams: params }); + } else { + // Just open the page as root. + await this.navCtrl.navigateRoot(page, { queryParams: params }); + } + } + + /** + * Go to the initial page of a site depending on 'userhomepage' setting. + * + * @param options Options. + * @return Promise resolved when done. + */ + goToSiteInitialPage(options?: CoreNavHelperOpenMainMenuOptions): Promise { + return this.openMainMenu(options); + } + + /** + * Check if the main menu is open. + * + * @return Whether the main menu is open. + */ + isMainMenuOpen(): boolean { + return typeof this.mainMenuOpen != 'undefined'; + } + + /** + * Load a certain page in the main menu. + * + * @param page Route of the page to load. + * @param params Params to pass to the page. + */ + loadPageInMainMenu(page: string, params?: Params): void { + if (!this.isMainMenuOpen()) { + // Main menu not open. Store the page to be loaded later. + this.pageToLoad = { + page: page, + params: params, + time: Date.now(), + }; + + return; + } + + if (page == CoreNavHelperService.OPEN_COURSE) { + // @todo Use the openCourse function. + } else { + CoreEvents.trigger(CoreEvents.LOAD_PAGE_MAIN_MENU, { redirectPage: page, redirectParams: params }); + } + } + + /** + * Load a site and load a certain page in that site. + * + * @param siteId Site to load. + * @param page Name of the page to load. + * @param params Params to pass to the page. + * @return Promise resolved when done. + */ + protected async loadSiteAndPage(siteId: string, page: string, params?: Params): Promise { + if (siteId == CoreConstants.NO_SITE_ID) { + // Page doesn't belong to a site, just load the page. + await this.navCtrl.navigateRoot(page, params); + + return; + } + + const modal = await CoreDomUtils.instance.showModalLoading(); + + try { + const loggedIn = await CoreSites.instance.loadSite(siteId, page, params); + + if (!loggedIn) { + return; + } + + await this.openMainMenu({ + redirectPage: page, + redirectParams: params, + }); + } catch (error) { + // Site doesn't exist. + await this.navCtrl.navigateRoot('/login/sites'); + } finally { + modal.dismiss(); + } + } + + /** + * Open the main menu, loading a certain page. + * + * @param options Options. + * @return Promise resolved when done. + */ + protected async openMainMenu(options?: CoreNavHelperOpenMainMenuOptions): Promise { + + // Due to DeepLinker, we need to remove the path from the URL before going to main menu. + // IonTabs checks the URL to determine which path to load for deep linking, so we clear the URL. + // @todo this.location.replaceState(''); + + if (options?.redirectPage == CoreNavHelperService.OPEN_COURSE) { + // Load the main menu first, and then open the course. + try { + await this.navCtrl.navigateRoot('/'); + } finally { + // @todo: Open course. + } + } else { + // Open the main menu. + const queryParams: Params = Object.assign({}, options); + delete queryParams.navigationOptions; + + await this.navCtrl.navigateRoot('/', { + queryParams, + ...options?.navigationOptions, + }); + } + } + + /** + * Open a new page, setting it as the root page and loading the right site if needed. + * + * @param page Name of the page to load. Special cases: OPEN_COURSE (to open course page). + * @param params Params to pass to the page. + * @param siteId Site to load. If not defined, current site. + * @return Promise resolved when done. + */ + async openInSiteMainMenu(page: string, params?: Params, siteId?: string): Promise { + siteId = siteId || CoreSites.instance.getCurrentSiteId(); + + if (!CoreSites.instance.isLoggedIn()) { + if (siteId) { + await this.loadSiteAndPage(siteId, page, params); + } else { + await this.navCtrl.navigateRoot('/login/sites'); + } + + return; + } + + if (siteId && siteId != CoreSites.instance.getCurrentSiteId()) { + // Target page belongs to a different site. Change site. + // @todo: Check site plugins. + await CoreSites.instance.logout(); + + await this.loadSiteAndPage(siteId, page, params); + } else { + // Current page, open it in main menu. + this.loadPageInMainMenu(page, params); + } + } + + /** + * Set a main menu as open or not. + * + * @param id Main menu ID. + * @param open Whether it's open or not. + */ + setMainMenuOpen(id: number, open: boolean): void { + if (open) { + this.mainMenuOpen = id; + CoreEvents.trigger(CoreEvents.MAIN_MENU_OPEN); + } else if (this.mainMenuOpen == id) { + delete this.mainMenuOpen; + } + } + +} + +export class CoreNavHelper extends makeSingleton(CoreNavHelperService) {} + +export type CoreNavHelperOpenMainMenuOptions = { + redirectPage?: string; // Route of the page to open in main menu. If not defined, default tab will be selected. + redirectParams?: Params; // Params to pass to the selected tab if any. + urlToOpen?: string; // URL to open once the main menu is loaded. + navigationOptions?: NavigationOptions; // Navigation options. +};