MOBILE-3592 core: Implement new service CoreNavHelper

main
Dani Palou 2020-12-11 13:14:34 +01:00
parent 186593b09f
commit 0819947072
20 changed files with 442 additions and 274 deletions

View File

@ -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,
}));
});
}

View File

@ -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);
},
}];
}

View File

@ -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);
}

View File

@ -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<void> {
siteId = siteId || CoreSites.instance.getCurrentSiteId();
const deferred = CoreUtils.instance.promiseDefer<void>();
// 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<void> {
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());
}
}

View File

@ -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);
}
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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');

View File

@ -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,
});

View File

@ -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 {

View File

@ -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);

View File

@ -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);

View File

@ -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 = '<img src="assets/img/login/faq_url.png" role="presentation">';
static readonly FAQ_QRCODE_IMAGE_HTML = '<img src="assets/img/login/faq_qrcode.png" role="presentation">';
@ -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<void> {
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<void> {
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<void> {
return this.openMainMenu(options);
goToSiteInitialPage(options?: CoreNavHelperOpenMainMenuOptions): Promise<void> {
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<void> {
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<void> {
// 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<void> {
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<void> {
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.
};

View File

@ -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();
}

View File

@ -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<CoreContentLinksAction[]> {
return [{
action: (siteId: string): void => {
CoreContentLinksHelper.instance.goInSite('sitehome', [], siteId);
CoreNavHelper.instance.goInSite('sitehome', [], siteId);
},
}];
}

View File

@ -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);
}
},
}];

View File

@ -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);
},
}];
}

View File

@ -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);
},
}];
}

View File

@ -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<SchemaVersionsManager>;
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);
}
/**

View File

@ -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<void> {
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<void> {
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<void> {
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<void> {
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<void> {
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<void> {
// 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<void> {
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.
};