MOBILE-3742 core: Support auto successive navigations
parent
ef2f68a5fd
commit
82c00bae84
|
@ -51,9 +51,6 @@ export class AddonBadgesIssuedBadgePage implements OnInit {
|
|||
* View loaded.
|
||||
*/
|
||||
ngOnInit(): void {
|
||||
this.route.queryParams.subscribe(() => {
|
||||
this.badgeLoaded = false;
|
||||
|
||||
this.courseId = CoreNavigator.getRouteNumberParam('courseId') || this.courseId; // Use 0 for site badges.
|
||||
this.userId = CoreNavigator.getRouteNumberParam('userId') || CoreSites.getCurrentSite()!.getUserId();
|
||||
this.badgeHash = CoreNavigator.getRouteParam('badgeHash') || '';
|
||||
|
@ -61,7 +58,6 @@ export class AddonBadgesIssuedBadgePage implements OnInit {
|
|||
this.fetchIssuedBadge().finally(() => {
|
||||
this.badgeLoaded = true;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -24,7 +24,7 @@ export const AddonCalendarEditRoute: Route = {
|
|||
};
|
||||
|
||||
export const AddonCalendarEventRoute: Route ={
|
||||
path: 'event',
|
||||
path: 'event/:id',
|
||||
loadChildren: () => import('@/addons/calendar/pages/event/event.module').then(m => m.AddonCalendarEventPageModule),
|
||||
};
|
||||
|
||||
|
|
|
@ -525,7 +525,7 @@ export class AddonCalendarDayPage implements OnInit, OnDestroy {
|
|||
// It's an offline event, go to the edit page.
|
||||
this.openEdit(eventId);
|
||||
} else {
|
||||
CoreNavigator.navigateToSitePath('/calendar/event', { params: { id: eventId } });
|
||||
CoreNavigator.navigateToSitePath(`/calendar/event/${eventId}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -155,22 +155,10 @@ export class AddonCalendarEventPage implements OnInit, OnDestroy {
|
|||
* View loaded.
|
||||
*/
|
||||
ngOnInit(): void {
|
||||
this.route.queryParams.subscribe(() => {
|
||||
this.eventLoaded = false;
|
||||
|
||||
const eventId = CoreNavigator.getRouteNumberParam('id');
|
||||
if (!eventId) {
|
||||
CoreDomUtils.showErrorModal('Event ID not supplied.');
|
||||
CoreNavigator.back();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this.eventId = eventId;
|
||||
this.eventId = CoreNavigator.getRouteNumberParam('id')!;
|
||||
this.syncIcon = CoreConstants.ICON_LOADING;
|
||||
|
||||
this.fetchEvent();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -46,7 +46,6 @@ export class AddonCalendarIndexPage implements OnInit, OnDestroy {
|
|||
@ViewChild(AddonCalendarCalendarComponent) calendarComponent?: AddonCalendarCalendarComponent;
|
||||
@ViewChild(AddonCalendarUpcomingEventsComponent) upcomingEventsComponent?: AddonCalendarUpcomingEventsComponent;
|
||||
|
||||
protected eventId?: number;
|
||||
protected currentSiteId: string;
|
||||
|
||||
// Observers.
|
||||
|
@ -167,8 +166,7 @@ export class AddonCalendarIndexPage implements OnInit, OnDestroy {
|
|||
ngOnInit(): void {
|
||||
this.notificationsEnabled = CoreLocalNotifications.isAvailable();
|
||||
|
||||
this.route.queryParams.subscribe(() => {
|
||||
this.eventId = CoreNavigator.getRouteNumberParam('eventId');
|
||||
this.route.queryParams.subscribe(async () => {
|
||||
this.filter.courseId = CoreNavigator.getRouteNumberParam('courseId');
|
||||
this.year = CoreNavigator.getRouteNumberParam('year');
|
||||
this.month = CoreNavigator.getRouteNumberParam('month');
|
||||
|
@ -176,11 +174,6 @@ export class AddonCalendarIndexPage implements OnInit, OnDestroy {
|
|||
this.showCalendar = !this.loadUpcoming;
|
||||
this.filter.filtered = !!this.filter.courseId;
|
||||
|
||||
if (this.eventId) {
|
||||
// There is an event to load, open the event in a new state.
|
||||
this.gotoEvent(this.eventId);
|
||||
}
|
||||
|
||||
this.fetchData(true, false);
|
||||
});
|
||||
}
|
||||
|
@ -311,7 +304,7 @@ export class AddonCalendarIndexPage implements OnInit, OnDestroy {
|
|||
// It's an offline event, go to the edit page.
|
||||
this.openEdit(eventId);
|
||||
} else {
|
||||
CoreNavigator.navigateToSitePath('/calendar/event', { params: { id: eventId } });
|
||||
CoreNavigator.navigateToSitePath(`/calendar/event/${eventId}`);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -244,14 +244,7 @@ export class AddonCalendarListPage implements OnInit, OnDestroy {
|
|||
* View loaded.
|
||||
*/
|
||||
async ngOnInit(): Promise<void> {
|
||||
this.eventId = CoreNavigator.getRouteNumberParam('eventId');
|
||||
this.filter.courseId = CoreNavigator.getRouteNumberParam('courseId') || -1;
|
||||
|
||||
if (this.eventId) {
|
||||
// There is an event to load, open the event in a new state.
|
||||
this.gotoEvent(this.eventId);
|
||||
}
|
||||
|
||||
this.syncIcon = CoreConstants.ICON_LOADING;
|
||||
|
||||
await this.fetchData(false, true, false);
|
||||
|
|
|
@ -373,7 +373,14 @@ export class AddonCalendarProvider {
|
|||
|
||||
CoreNavigator.navigateToSitePath(
|
||||
pageName,
|
||||
{ params: { eventId: notification.eventId }, siteId: notification.siteId },
|
||||
{
|
||||
siteId: notification.siteId,
|
||||
preferCurrentTab: false,
|
||||
nextNavigation: {
|
||||
path: `calendar/event/${notification.eventId}`,
|
||||
isSitePath: true,
|
||||
},
|
||||
},
|
||||
);
|
||||
}
|
||||
},
|
||||
|
|
|
@ -58,8 +58,11 @@ export class AddonCalendarViewLinkHandlerService extends CoreContentLinksHandler
|
|||
stateParams.year = date.getFullYear();
|
||||
stateParams.month = date.getMonth() + 1;
|
||||
|
||||
// @todo: Add checkMenu param.
|
||||
CoreNavigator.navigateToSitePath('/calendar/index', { params: stateParams, siteId });
|
||||
CoreNavigator.navigateToSitePath('/calendar/index', {
|
||||
params: stateParams,
|
||||
siteId,
|
||||
preferCurrentTab: false,
|
||||
});
|
||||
|
||||
} else if (params.view == 'day') {
|
||||
// Daily view, open the page.
|
||||
|
@ -82,8 +85,11 @@ export class AddonCalendarViewLinkHandlerService extends CoreContentLinksHandler
|
|||
upcoming: true,
|
||||
};
|
||||
|
||||
// @todo: Add checkMenu param.
|
||||
CoreNavigator.navigateToSitePath('/calendar/index', { params: stateParams, siteId });
|
||||
CoreNavigator.navigateToSitePath('/calendar/index', {
|
||||
params: stateParams,
|
||||
siteId,
|
||||
preferCurrentTab: false,
|
||||
});
|
||||
|
||||
}
|
||||
},
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { Component, Input, OnInit } from '@angular/core';
|
||||
import { IonRefresher } from '@ionic/angular';
|
||||
import {
|
||||
AddonMessagesConversationFormatted,
|
||||
|
@ -22,7 +22,6 @@ import {
|
|||
import { CoreDomUtils } from '@services/utils/dom';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { ModalController } from '@singletons';
|
||||
import { CoreNavigator } from '@services/navigator';
|
||||
|
||||
/**
|
||||
* Component that displays the list of conversations, including group conversations.
|
||||
|
@ -33,14 +32,14 @@ import { CoreNavigator } from '@services/navigator';
|
|||
})
|
||||
export class AddonMessagesConversationInfoComponent implements OnInit {
|
||||
|
||||
@Input() conversationId = 0;
|
||||
|
||||
loaded = false;
|
||||
conversation?: AddonMessagesConversationFormatted;
|
||||
members: AddonMessagesConversationMember[] = [];
|
||||
canLoadMore = false;
|
||||
loadMoreError = false;
|
||||
|
||||
protected conversationId!: number;
|
||||
|
||||
constructor(
|
||||
protected route: ActivatedRoute,
|
||||
) {
|
||||
|
@ -50,14 +49,9 @@ export class AddonMessagesConversationInfoComponent implements OnInit {
|
|||
* Component loaded.
|
||||
*/
|
||||
ngOnInit(): void {
|
||||
this.route.queryParams.subscribe(async () => {
|
||||
this.conversationId = CoreNavigator.getRouteNumberParam('conversationId') || 0;
|
||||
|
||||
this.loaded = false;
|
||||
this.fetchData().finally(() => {
|
||||
this.loaded = true;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -84,8 +84,7 @@ export class AddonMessagesContacts35Page implements OnInit, OnDestroy {
|
|||
/**
|
||||
* Component loaded.
|
||||
*/
|
||||
ngOnInit(): void {
|
||||
this.route.queryParams.subscribe(async () => {
|
||||
async ngOnInit(): Promise<void> {
|
||||
const discussionUserId = CoreNavigator.getRouteNumberParam('discussionUserId') ||
|
||||
CoreNavigator.getRouteNumberParam('userId') || undefined;
|
||||
|
||||
|
@ -119,7 +118,6 @@ export class AddonMessagesContacts35Page implements OnInit, OnDestroy {
|
|||
} finally {
|
||||
this.loaded = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -136,21 +136,11 @@ export class AddonMessagesDiscussions35Page implements OnInit, OnDestroy {
|
|||
/**
|
||||
* Component loaded.
|
||||
*/
|
||||
ngOnInit(): void {
|
||||
async ngOnInit(): Promise<void> {
|
||||
this.route.queryParams.subscribe(async (params) => {
|
||||
const discussionUserId = CoreNavigator.getRouteNumberParam('discussionUserId', { params }) ||
|
||||
CoreNavigator.getRouteNumberParam('userId', { params }) || undefined;
|
||||
|
||||
if (this.loaded && this.discussionUserId == discussionUserId) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.discussionUserId = discussionUserId;
|
||||
|
||||
if (this.discussionUserId) {
|
||||
// There is a discussion to load, open the discussion in a new state.
|
||||
this.gotoDiscussion(this.discussionUserId);
|
||||
}
|
||||
// When a child page loads this callback is triggered too.
|
||||
this.discussionUserId = CoreNavigator.getRouteNumberParam('userId', { params }) ?? this.discussionUserId;
|
||||
});
|
||||
|
||||
await this.fetchData();
|
||||
|
||||
|
@ -158,7 +148,6 @@ export class AddonMessagesDiscussions35Page implements OnInit, OnDestroy {
|
|||
// Take first and load it.
|
||||
this.gotoDiscussion(this.discussions[0].message!.user);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -87,8 +87,6 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
|
|||
|
||||
protected siteId: string;
|
||||
protected currentUserId: number;
|
||||
protected conversationId?: number;
|
||||
protected discussionUserId?: number;
|
||||
protected newMessagesObserver: CoreEventObserver;
|
||||
protected pushObserver: Subscription;
|
||||
protected appResumeSubscription: Subscription;
|
||||
|
@ -270,21 +268,18 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
|
|||
/**
|
||||
* Component loaded.
|
||||
*/
|
||||
ngOnInit(): void {
|
||||
async ngOnInit(): Promise<void> {
|
||||
this.route.queryParams.subscribe(async (params) => {
|
||||
// Conversation to load.
|
||||
this.conversationId = CoreNavigator.getRouteNumberParam('conversationId', { params }) || undefined;
|
||||
if (!this.conversationId) {
|
||||
this.discussionUserId = CoreNavigator.getRouteNumberParam('discussionUserId', { params }) || undefined;
|
||||
}
|
||||
|
||||
if (this.conversationId || this.discussionUserId) {
|
||||
// There is a discussion to load, open the discussion in a new state.
|
||||
this.gotoConversation(this.conversationId, this.discussionUserId);
|
||||
}
|
||||
// When a child page loads this callback is triggered too.
|
||||
this.selectedConversationId =
|
||||
CoreNavigator.getRouteNumberParam('conversationId', { params }) ?? this.selectedConversationId;
|
||||
this.selectedUserId =
|
||||
CoreNavigator.getRouteNumberParam('userId', { params }) ?? this.selectedUserId;
|
||||
});
|
||||
|
||||
await this.fetchData();
|
||||
if (!this.conversationId && !this.discussionUserId && CoreScreen.isTablet) {
|
||||
|
||||
if (!this.selectedConversationId && !this.selectedUserId && CoreScreen.isTablet) {
|
||||
// Load the first conversation.
|
||||
let conversation: AddonMessagesConversationForList;
|
||||
const expandedOption = this.getExpandedOption();
|
||||
|
@ -297,7 +292,6 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
|
|||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -322,7 +316,7 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
|
|||
await Promise.all(promises);
|
||||
|
||||
// The expanded status hasn't been initialized. Do it now.
|
||||
if (typeof this.favourites.expanded == 'undefined' && this.conversationId || this.discussionUserId) {
|
||||
if (typeof this.favourites.expanded == 'undefined' && (this.selectedConversationId || this.selectedUserId)) {
|
||||
// A certain conversation should be opened.
|
||||
// We don't know which option it belongs to, so we need to fetch the data for all of them.
|
||||
const promises: Promise<void>[] = [];
|
||||
|
@ -333,7 +327,7 @@ export class AddonMessagesGroupConversationsPage implements OnInit, OnDestroy {
|
|||
|
||||
await Promise.all(promises);
|
||||
// All conversations have been loaded, find the one we need to load and expand its option.
|
||||
const conversation = this.findConversation(this.conversationId, this.discussionUserId);
|
||||
const conversation = this.findConversation(this.selectedConversationId, this.selectedUserId);
|
||||
if (conversation) {
|
||||
const option = this.getConversationOption(conversation);
|
||||
|
||||
|
|
|
@ -39,7 +39,10 @@ export class AddonMessagesIndexLinkHandlerService extends CoreContentLinksHandle
|
|||
action: async (siteId): Promise<void> => {
|
||||
const pageName = await AddonMessages.getMainMessagesPagePathInSite(siteId);
|
||||
|
||||
CoreNavigator.navigateToSitePath(pageName, { siteId });
|
||||
CoreNavigator.navigateToSitePath(pageName, {
|
||||
siteId,
|
||||
preferCurrentTab: false,
|
||||
});
|
||||
},
|
||||
}];
|
||||
}
|
||||
|
|
|
@ -63,16 +63,29 @@ export class AddonMessagesPushClickHandlerService implements CorePushNotificatio
|
|||
const enabled = await AddonMessages.isGroupMessagingEnabledInSite(notification.site);
|
||||
const pageName = await AddonMessages.getMainMessagesPagePathInSite(notification.site);
|
||||
|
||||
const pageParams: Params = {};
|
||||
let nextPageParams: Params | undefined;
|
||||
|
||||
// Check if we have enough information to open the conversation.
|
||||
if (notification.convid && enabled) {
|
||||
pageParams.conversationId = Number(notification.convid);
|
||||
nextPageParams = {
|
||||
conversationId: Number(notification.convid),
|
||||
};
|
||||
} else if (notification.userfromid) {
|
||||
pageParams.discussionUserId = Number(notification.userfromid);
|
||||
nextPageParams = {
|
||||
userId: Number(notification.userfromid),
|
||||
};
|
||||
}
|
||||
|
||||
await CoreNavigator.navigateToSitePath(pageName, { params: pageParams, siteId: notification.site });
|
||||
await CoreNavigator.navigateToSitePath(pageName, {
|
||||
siteId: notification.site,
|
||||
preferCurrentTab: false,
|
||||
nextNavigation: nextPageParams ?
|
||||
{
|
||||
path: 'discussion',
|
||||
options: { params: nextPageParams },
|
||||
} :
|
||||
undefined,
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -125,7 +125,10 @@ export class AddonNotificationsPushClickHandlerService implements CorePushNotifi
|
|||
|
||||
await CoreNavigator.navigateToSitePath(
|
||||
AddonNotificationsMainMenuHandlerService.PAGE_NAME,
|
||||
{ siteId: notification.site },
|
||||
{
|
||||
siteId: notification.site,
|
||||
preferCurrentTab: false,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
import { BehaviorSubject, Subject } from 'rxjs';
|
||||
import { CoreEvents } from '@singletons/events';
|
||||
import { CoreDelegate, CoreDelegateDisplayHandler, CoreDelegateToDisplay } from './delegate';
|
||||
import { CoreUtils } from '@services/utils/utils';
|
||||
|
||||
/**
|
||||
* Superclass to help creating sorted delegates.
|
||||
|
@ -76,6 +77,30 @@ export class CoreSortedDelegate<
|
|||
return this.sortedHandlersRxJs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the handlers for the current site once they're loaded.
|
||||
*
|
||||
* @return Promise resolved with the handlers.
|
||||
*/
|
||||
async getHandlersWhenLoaded(): Promise<DisplayType[]> {
|
||||
if (this.loaded) {
|
||||
return this.sortedHandlers;
|
||||
}
|
||||
|
||||
const deferred = CoreUtils.promiseDefer<DisplayType[]>();
|
||||
|
||||
const subscription = this.getHandlersObservable().subscribe((handlers) => {
|
||||
if (this.loaded) {
|
||||
subscription?.unsubscribe();
|
||||
|
||||
// Return main handlers.
|
||||
deferred.resolve(handlers);
|
||||
}
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update handlers Data.
|
||||
*/
|
||||
|
|
|
@ -36,7 +36,10 @@ export class CoreGradesOverviewLinkHandlerService extends CoreContentLinksHandle
|
|||
getActions(): CoreContentLinksAction[] | Promise<CoreContentLinksAction[]> {
|
||||
return [{
|
||||
action: siteId => {
|
||||
CoreNavigator.navigateToSitePath('/grades', { siteId });
|
||||
CoreNavigator.navigateToSitePath('/grades', {
|
||||
siteId,
|
||||
preferCurrentTab: false,
|
||||
});
|
||||
},
|
||||
}];
|
||||
}
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
// limitations under the License.
|
||||
|
||||
import { Component, OnInit, OnDestroy, ViewChild, ElementRef } from '@angular/core';
|
||||
import { Params } from '@angular/router';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
|
||||
import { CoreApp } from '@services/app';
|
||||
|
@ -24,7 +23,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 { CoreNavigator } from '@services/navigator';
|
||||
import { CoreNavigationOptions, CoreNavigator, CoreRedirectPayload } from '@services/navigator';
|
||||
import { CoreForms } from '@singletons/form';
|
||||
|
||||
/**
|
||||
|
@ -55,7 +54,7 @@ export class CoreLoginReconnectPage implements OnInit, OnDestroy {
|
|||
showScanQR = false;
|
||||
|
||||
protected page?: string;
|
||||
protected pageParams?: Params;
|
||||
protected pageOptions?: CoreNavigationOptions;
|
||||
protected siteConfig?: CoreSitePublicConfigResponse;
|
||||
protected viewLeft = false;
|
||||
protected eventThrown = false;
|
||||
|
@ -83,7 +82,7 @@ export class CoreLoginReconnectPage implements OnInit, OnDestroy {
|
|||
|
||||
this.siteUrl = siteId;
|
||||
this.page = CoreNavigator.getRouteParam('pageName');
|
||||
this.pageParams = CoreNavigator.getRouteParam('pageParams');
|
||||
this.pageOptions = CoreNavigator.getRouteParam('pageOptions');
|
||||
this.showScanQR = CoreLoginHelper.displayQRInSiteScreen() || CoreLoginHelper.displayQRInCredentialsScreen();
|
||||
|
||||
try {
|
||||
|
@ -214,8 +213,8 @@ export class CoreLoginReconnectPage implements OnInit, OnDestroy {
|
|||
await CoreNavigator.navigateToSiteHome({
|
||||
params: {
|
||||
redirectPath: this.page,
|
||||
redirectParams: this.pageParams,
|
||||
},
|
||||
redirectOptions: this.pageOptions,
|
||||
} as CoreRedirectPayload,
|
||||
});
|
||||
} catch (error) {
|
||||
CoreLoginHelper.treatUserTokenError(this.siteUrl, error, this.username, password);
|
||||
|
@ -244,7 +243,15 @@ export class CoreLoginReconnectPage implements OnInit, OnDestroy {
|
|||
* @param provider The provider that was clicked.
|
||||
*/
|
||||
oauthClicked(provider: CoreSiteIdentityProvider): void {
|
||||
if (!CoreLoginHelper.openBrowserForOAuthLogin(this.siteUrl, provider, this.siteConfig?.launchurl)) {
|
||||
const result = CoreLoginHelper.openBrowserForOAuthLogin(
|
||||
this.siteUrl,
|
||||
provider,
|
||||
this.siteConfig?.launchurl,
|
||||
this.page,
|
||||
this.pageOptions,
|
||||
);
|
||||
|
||||
if (!result) {
|
||||
CoreDomUtils.showErrorModal('Invalid data.');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ import { CoreWSError } from '@classes/errors/wserror';
|
|||
import { makeSingleton, Translate } from '@singletons';
|
||||
import { CoreLogger } from '@singletons/logger';
|
||||
import { CoreUrl } from '@singletons/url';
|
||||
import { CoreNavigator } from '@services/navigator';
|
||||
import { CoreNavigationOptions, CoreNavigator } from '@services/navigator';
|
||||
import { CoreCanceledError } from '@classes/errors/cancelederror';
|
||||
import { CoreCustomURLSchemes } from '@services/urlschemes';
|
||||
|
||||
|
@ -461,7 +461,7 @@ export class CoreLoginHelperProvider {
|
|||
...options,
|
||||
params: {
|
||||
redirectPath: page,
|
||||
redirectParams: params,
|
||||
redirectOptions: { params },
|
||||
urlToOpen: url,
|
||||
},
|
||||
});
|
||||
|
@ -549,10 +549,10 @@ export class CoreLoginHelperProvider {
|
|||
* Check if current site is logged out, triggering mmCoreEventSessionExpired if it is.
|
||||
*
|
||||
* @param pageName Name of the page to go once authenticated if logged out. If not defined, site initial page.
|
||||
* @param params Params of the page to go once authenticated if logged out.
|
||||
* @param options Options of the page to go once authenticated if logged out.
|
||||
* @return True if user is logged out, false otherwise.
|
||||
*/
|
||||
isSiteLoggedOut(pageName?: string, params?: Params): boolean {
|
||||
isSiteLoggedOut(pageName?: string, options?: CoreNavigationOptions): boolean {
|
||||
const site = CoreSites.getCurrentSite();
|
||||
if (!site) {
|
||||
return false;
|
||||
|
@ -561,7 +561,7 @@ export class CoreLoginHelperProvider {
|
|||
if (site.isLoggedOut()) {
|
||||
CoreEvents.trigger(CoreEvents.SESSION_EXPIRED, {
|
||||
pageName,
|
||||
params,
|
||||
options,
|
||||
}, site.getId());
|
||||
|
||||
return true;
|
||||
|
@ -633,7 +633,7 @@ export class CoreLoginHelperProvider {
|
|||
* @param provider The identity provider.
|
||||
* @param launchUrl The URL to open for SSO. If not defined, tool/mobile launch URL will be used.
|
||||
* @param pageName Name of the page to go once authenticated. If not defined, site initial page.
|
||||
* @param pageParams Params of the state to go once authenticated.
|
||||
* @param pageOptions Options of the page to go once authenticated.
|
||||
* @return True if success, false if error.
|
||||
*/
|
||||
openBrowserForOAuthLogin(
|
||||
|
@ -641,7 +641,7 @@ export class CoreLoginHelperProvider {
|
|||
provider: CoreSiteIdentityProvider,
|
||||
launchUrl?: string,
|
||||
pageName?: string,
|
||||
pageParams?: Params,
|
||||
pageOptions?: CoreNavigationOptions,
|
||||
): boolean {
|
||||
launchUrl = launchUrl || siteUrl + '/admin/tool/mobile/launch.php';
|
||||
if (!provider || !provider.url) {
|
||||
|
@ -655,7 +655,7 @@ export class CoreLoginHelperProvider {
|
|||
}
|
||||
|
||||
const service = CoreSites.determineService(siteUrl);
|
||||
const loginUrl = this.prepareForSSOLogin(siteUrl, service, launchUrl, pageName, pageParams, {
|
||||
const loginUrl = this.prepareForSSOLogin(siteUrl, service, launchUrl, pageName, pageOptions, {
|
||||
oauthsso: params.id,
|
||||
});
|
||||
|
||||
|
@ -676,7 +676,7 @@ export class CoreLoginHelperProvider {
|
|||
* @param service The service to use. If not defined, external service will be used.
|
||||
* @param launchUrl The URL to open for SSO. If not defined, local_mobile launch URL will be used.
|
||||
* @param pageName Name of the page to go once authenticated. If not defined, site initial page.
|
||||
* @param pageParams Params of the state to go once authenticated.
|
||||
* @param pageOptions Options of the state to go once authenticated.
|
||||
*/
|
||||
openBrowserForSSOLogin(
|
||||
siteUrl: string,
|
||||
|
@ -684,9 +684,9 @@ export class CoreLoginHelperProvider {
|
|||
service?: string,
|
||||
launchUrl?: string,
|
||||
pageName?: string,
|
||||
pageParams?: Params,
|
||||
pageOptions?: CoreNavigationOptions,
|
||||
): void {
|
||||
const loginUrl = this.prepareForSSOLogin(siteUrl, service, launchUrl, pageName, pageParams);
|
||||
const loginUrl = this.prepareForSSOLogin(siteUrl, service, launchUrl, pageName, pageOptions);
|
||||
|
||||
if (this.isSSOEmbeddedBrowser(typeOfLogin)) {
|
||||
CoreUtils.openInApp(loginUrl, {
|
||||
|
@ -797,7 +797,7 @@ export class CoreLoginHelperProvider {
|
|||
* @param service The service to use. If not defined, external service will be used.
|
||||
* @param launchUrl The URL to open for SSO. If not defined, local_mobile launch URL will be used.
|
||||
* @param pageName Name of the page to go once authenticated. If not defined, site initial page.
|
||||
* @param pageParams Params of the state to go once authenticated.
|
||||
* @param pageOptions Options of the page to go once authenticated.
|
||||
* @param urlParams Other params to add to the URL.
|
||||
* @return Login Url.
|
||||
*/
|
||||
|
@ -806,7 +806,7 @@ export class CoreLoginHelperProvider {
|
|||
service?: string,
|
||||
launchUrl?: string,
|
||||
pageName?: string,
|
||||
pageParams?: Params,
|
||||
pageOptions?: CoreNavigationOptions,
|
||||
urlParams?: CoreUrlParams,
|
||||
): string {
|
||||
|
||||
|
@ -829,7 +829,7 @@ export class CoreLoginHelperProvider {
|
|||
siteUrl: siteUrl,
|
||||
passport: passport,
|
||||
pageName: pageName || '',
|
||||
pageParams: pageParams || {},
|
||||
pageOptions: pageOptions || {},
|
||||
ssoUrlParams: urlParams || {},
|
||||
}));
|
||||
|
||||
|
@ -917,7 +917,7 @@ export class CoreLoginHelperProvider {
|
|||
result.service,
|
||||
result.config?.launchurl,
|
||||
data.pageName,
|
||||
data.params,
|
||||
data.options,
|
||||
);
|
||||
} catch (error) {
|
||||
// User cancelled, logout him.
|
||||
|
@ -955,7 +955,7 @@ export class CoreLoginHelperProvider {
|
|||
providerToUse,
|
||||
result.config?.launchurl,
|
||||
data.pageName,
|
||||
data.params,
|
||||
data.options,
|
||||
);
|
||||
} catch (error) {
|
||||
// User cancelled, logout him.
|
||||
|
@ -982,7 +982,7 @@ export class CoreLoginHelperProvider {
|
|||
params: {
|
||||
siteId,
|
||||
pageName: data.pageName,
|
||||
pageParams: data.params,
|
||||
pageOptions: data.options,
|
||||
},
|
||||
reset: true,
|
||||
}));
|
||||
|
@ -1213,7 +1213,7 @@ export class CoreLoginHelperProvider {
|
|||
token: params[1],
|
||||
privateToken: params[2],
|
||||
pageName: data.pageName,
|
||||
pageParams: data.pageParams,
|
||||
pageOptions: data.pageOptions,
|
||||
ssoUrlParams: data.ssoUrlParams,
|
||||
};
|
||||
} else {
|
||||
|
@ -1357,9 +1357,9 @@ export interface CoreLoginSSOData {
|
|||
pageName?: string;
|
||||
|
||||
/**
|
||||
* Params to page to the page.
|
||||
* Options of the navigation to the page.
|
||||
*/
|
||||
pageParams?: Params;
|
||||
pageOptions?: CoreNavigationOptions;
|
||||
|
||||
/**
|
||||
* Other params added to the login url.
|
||||
|
@ -1450,6 +1450,6 @@ type StoredLoginLaunchData = {
|
|||
siteUrl: string;
|
||||
passport: number;
|
||||
pageName: string;
|
||||
pageParams: Params;
|
||||
pageOptions: CoreNavigationOptions;
|
||||
ssoUrlParams: CoreUrlParams;
|
||||
};
|
||||
|
|
|
@ -64,7 +64,7 @@ export class CoreMainMenuHomePage implements OnInit {
|
|||
if (params.redirectPath) {
|
||||
this.pendingRedirect = {
|
||||
redirectPath: params.redirectPath,
|
||||
redirectParams: params.redirectParams,
|
||||
redirectOptions: params.redirectOptions,
|
||||
};
|
||||
}
|
||||
});
|
||||
|
@ -141,7 +141,7 @@ export class CoreMainMenuHomePage implements OnInit {
|
|||
* @param data Data received.
|
||||
*/
|
||||
protected handleRedirect(data: CoreRedirectPayload): void {
|
||||
const params = data.redirectParams;
|
||||
const params = data.redirectOptions?.params;
|
||||
const coursePathMatches = data.redirectPath.match(/^course\/(\d+)\/?$/);
|
||||
|
||||
if (coursePathMatches) {
|
||||
|
@ -152,7 +152,7 @@ export class CoreMainMenuHomePage implements OnInit {
|
|||
}
|
||||
} else {
|
||||
CoreNavigator.navigateToSitePath(data.redirectPath, {
|
||||
params: data.redirectParams,
|
||||
...data.redirectOptions,
|
||||
preferCurrentTab: false,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -42,10 +42,10 @@ export class CoreMainMenuProvider {
|
|||
*
|
||||
* @return Promise resolved with the current main menu handlers.
|
||||
*/
|
||||
getCurrentMainMenuHandlers(): CoreMainMenuHandlerToDisplay[] {
|
||||
return CoreMainMenuDelegate.getHandlers()
|
||||
.filter(handler => !handler.onlyInMore)
|
||||
.slice(0, this.getNumItems());
|
||||
async getCurrentMainMenuHandlers(): Promise<CoreMainMenuHandlerToDisplay[]> {
|
||||
const handlers = await CoreMainMenuDelegate.getHandlersWhenLoaded();
|
||||
|
||||
return handlers.filter(handler => !handler.onlyInMore).slice(0, this.getNumItems());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -215,7 +215,11 @@ export class CoreMainMenuProvider {
|
|||
async isCurrentMainMenuHandler(pageName: string): Promise<boolean> {
|
||||
const handlers = await this.getCurrentMainMenuHandlers();
|
||||
|
||||
const handler = handlers.find((handler) => handler.page == pageName);
|
||||
const handler = handlers.find((handler) => {
|
||||
const tabRoot = /^[^/]+/.exec(handler.page)?.[0] ?? handler.page;
|
||||
|
||||
return tabRoot == pageName;
|
||||
});
|
||||
|
||||
return !!handler;
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import { CanActivate, CanLoad, UrlTree } from '@angular/router';
|
||||
import { CoreApp } from '@services/app';
|
||||
import { CoreRedirectPayload } from '@services/navigator';
|
||||
import { CoreSites } from '@services/sites';
|
||||
import { Router } from '@singletons';
|
||||
import { CoreConstants } from '../constants';
|
||||
|
@ -40,7 +41,7 @@ export class CoreRedirectGuard implements CanLoad, CanActivate {
|
|||
* Check if there is a pending redirect and trigger it.
|
||||
*/
|
||||
private async guard(): Promise<true | UrlTree> {
|
||||
const redirect = CoreApp.consumeRedirect();
|
||||
const redirect = CoreApp.consumeMemoryRedirect();
|
||||
|
||||
if (!redirect) {
|
||||
return true;
|
||||
|
@ -56,14 +57,14 @@ export class CoreRedirectGuard implements CanLoad, CanActivate {
|
|||
const loggedIn = await CoreSites.loadSite(
|
||||
redirect.siteId,
|
||||
redirect.page,
|
||||
redirect.params,
|
||||
redirect.options,
|
||||
);
|
||||
const route = Router.parseUrl('/main/home');
|
||||
|
||||
route.queryParams = {
|
||||
redirectPath: redirect.page,
|
||||
redirectParams: redirect.params,
|
||||
};
|
||||
redirectOptions: redirect.options,
|
||||
} as CoreRedirectPayload;
|
||||
|
||||
return loggedIn ? route : true;
|
||||
}
|
||||
|
@ -78,8 +79,8 @@ export class CoreRedirectGuard implements CanLoad, CanActivate {
|
|||
|
||||
route.queryParams = {
|
||||
redirectPath: redirect.page,
|
||||
redirectParams: redirect.params,
|
||||
};
|
||||
redirectOptions: redirect.options,
|
||||
} as CoreRedirectPayload;
|
||||
|
||||
return route;
|
||||
}
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
// limitations under the License.
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Params } from '@angular/router';
|
||||
|
||||
import { CoreDB } from '@services/db';
|
||||
import { CoreEvents } from '@singletons/events';
|
||||
|
@ -25,6 +24,7 @@ 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 { CoreObject } from '@singletons/object';
|
||||
import { CoreNavigationOptions } from './navigator';
|
||||
|
||||
/**
|
||||
* Object responsible of managing schema versions.
|
||||
|
@ -554,7 +554,7 @@ export class CoreAppProvider {
|
|||
*
|
||||
* @return Redirect data if any.
|
||||
*/
|
||||
consumeRedirect(): CoreRedirectData | null {
|
||||
consumeMemoryRedirect(): CoreRedirectData | null {
|
||||
const redirect = this.getRedirect();
|
||||
|
||||
this.forgetRedirect();
|
||||
|
@ -583,14 +583,14 @@ export class CoreAppProvider {
|
|||
*
|
||||
* @param siteId Site ID.
|
||||
* @param page Page to go.
|
||||
* @param params Page params.
|
||||
* @param options Navigation options.
|
||||
*/
|
||||
storeRedirect(siteId: string, page: string, params: Params): void {
|
||||
storeRedirect(siteId: string, page: string, options: CoreNavigationOptions): void {
|
||||
try {
|
||||
const redirect: CoreRedirectData = {
|
||||
siteId,
|
||||
page,
|
||||
params,
|
||||
options,
|
||||
timemodified: Date.now(),
|
||||
};
|
||||
|
||||
|
@ -671,14 +671,14 @@ export type CoreRedirectData = {
|
|||
siteId?: string;
|
||||
|
||||
/**
|
||||
* Name of the page to redirect to.
|
||||
* Path of the page to redirect to.
|
||||
*/
|
||||
page?: string;
|
||||
|
||||
/**
|
||||
* Params to pass to the page.
|
||||
* Options of the navigation.
|
||||
*/
|
||||
params?: Params;
|
||||
options?: CoreNavigationOptions;
|
||||
|
||||
/**
|
||||
* Timestamp when this redirect was last modified.
|
||||
|
|
|
@ -39,7 +39,7 @@ const DEFAULT_MAIN_MENU_TAB = CoreMainMenuHomeHandlerService.PAGE_NAME;
|
|||
*/
|
||||
export type CoreRedirectPayload = {
|
||||
redirectPath: string;
|
||||
redirectParams?: Params;
|
||||
redirectOptions?: CoreNavigationOptions;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -50,6 +50,11 @@ export type CoreNavigationOptions = {
|
|||
params?: Params;
|
||||
reset?: boolean;
|
||||
preferCurrentTab?: boolean; // Default true.
|
||||
nextNavigation?: {
|
||||
path: string;
|
||||
isSitePath?: boolean;
|
||||
options?: CoreNavigationOptions;
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -149,6 +154,14 @@ export class CoreNavigatorService {
|
|||
? await NavController.navigateRoot(url, navigationOptions)
|
||||
: await NavController.navigateForward(url, navigationOptions);
|
||||
|
||||
if (options.nextNavigation?.path && navigationResult !== false) {
|
||||
if (options.nextNavigation.isSitePath) {
|
||||
return this.navigateToSitePath(options.nextNavigation.path, options.nextNavigation.options);
|
||||
}
|
||||
|
||||
return this.navigate(options.nextNavigation.path, options.nextNavigation.options);
|
||||
}
|
||||
|
||||
return navigationResult !== false;
|
||||
}
|
||||
|
||||
|
@ -211,7 +224,7 @@ export class CoreNavigatorService {
|
|||
if (CoreSites.isLoggedIn() && CoreSites.getCurrentSiteId() !== siteId) {
|
||||
if (CoreSitePlugins.hasSitePluginsLoaded) {
|
||||
// The site has site plugins so the app will be restarted. Store the data and logout.
|
||||
CoreApp.instance.storeRedirect(siteId, path, options.params || {});
|
||||
CoreApp.storeRedirect(siteId, path, options || {});
|
||||
|
||||
await CoreSites.logout();
|
||||
|
||||
|
@ -450,7 +463,7 @@ export class CoreNavigatorService {
|
|||
...options,
|
||||
params: {
|
||||
redirectPath: `/main/${DEFAULT_MAIN_MENU_TAB}/${path}`,
|
||||
redirectParams: options.params,
|
||||
redirectOptions: options.params || options.nextNavigation ? options : undefined,
|
||||
} as CoreRedirectPayload,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -50,6 +50,7 @@ import {
|
|||
} from '@services/database/sites';
|
||||
import { CoreArray } from '../singletons/array';
|
||||
import { CoreNetworkError } from '@classes/errors/network-error';
|
||||
import { CoreNavigationOptions } from './navigator';
|
||||
|
||||
export const CORE_SITE_SCHEMAS = new InjectionToken<CoreSiteSchema[]>('CORE_SITE_SCHEMAS');
|
||||
|
||||
|
@ -795,10 +796,10 @@ export class CoreSitesProvider {
|
|||
*
|
||||
* @param siteId ID of the site to load.
|
||||
* @param pageName Name of the page to go once authenticated if logged out. If not defined, site initial page.
|
||||
* @param params Params of the page to go once authenticated if logged out.
|
||||
* @param pageOptions Options of the navigation to pageName.
|
||||
* @return Promise resolved with true if site is loaded, resolved with false if cannot login.
|
||||
*/
|
||||
async loadSite(siteId: string, pageName?: string, params?: Record<string, unknown>): Promise<boolean> {
|
||||
async loadSite(siteId: string, pageName?: string, pageOptions?: CoreNavigationOptions): Promise<boolean> {
|
||||
this.logger.debug(`Load site ${siteId}`);
|
||||
|
||||
const site = await this.getSite(siteId);
|
||||
|
@ -809,7 +810,7 @@ export class CoreSitesProvider {
|
|||
// Logged out, trigger session expired event and stop.
|
||||
CoreEvents.trigger(CoreEvents.SESSION_EXPIRED, {
|
||||
pageName,
|
||||
params,
|
||||
options: pageOptions,
|
||||
}, site.getId());
|
||||
|
||||
return false;
|
||||
|
@ -822,7 +823,7 @@ export class CoreSitesProvider {
|
|||
// Local mobile was added. Throw invalid session to force reconnect and create a new token.
|
||||
CoreEvents.trigger(CoreEvents.SESSION_EXPIRED, {
|
||||
pageName,
|
||||
params,
|
||||
options: pageOptions,
|
||||
}, siteId);
|
||||
|
||||
return false;
|
||||
|
|
|
@ -153,9 +153,7 @@ export class CoreCustomURLSchemesProvider {
|
|||
// Site created and authenticated, open the page to go.
|
||||
if (data.pageName) {
|
||||
// Page defined, go to that page instead of site initial page.
|
||||
CoreNavigator.navigateToSitePath(data.pageName, {
|
||||
params: data.pageParams,
|
||||
});
|
||||
CoreNavigator.navigateToSitePath(data.pageName, data.pageOptions);
|
||||
} else {
|
||||
CoreNavigator.navigateToSiteHome();
|
||||
}
|
||||
|
@ -408,7 +406,7 @@ export class CoreCustomURLSchemesProvider {
|
|||
hasSitePluginsLoaded = CoreSitePlugins.hasSitePluginsLoaded;
|
||||
if (hasSitePluginsLoaded) {
|
||||
// Store the redirect since logout will restart the app.
|
||||
CoreApp.storeRedirect(CoreConstants.NO_SITE_ID, '/login/credentials', pageParams);
|
||||
CoreApp.storeRedirect(CoreConstants.NO_SITE_ID, '/login/credentials', { params: pageParams });
|
||||
}
|
||||
|
||||
await CoreSites.logout();
|
||||
|
|
|
@ -12,12 +12,12 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Params } from '@angular/router';
|
||||
import { Subject } from 'rxjs';
|
||||
|
||||
import { CoreLogger } from '@singletons/logger';
|
||||
import { CoreSite, CoreSiteInfoResponse, CoreSitePublicConfigResponse } from '@classes/site';
|
||||
import { CoreFilepoolComponentFileEventData } from '@services/filepool';
|
||||
import { CoreNavigationOptions } from '@services/navigator';
|
||||
|
||||
/**
|
||||
* Observer instance to stop listening to an event.
|
||||
|
@ -260,7 +260,7 @@ export type CoreEventSiteAddedData = CoreSiteInfoResponse;
|
|||
*/
|
||||
export type CoreEventSessionExpiredData = {
|
||||
pageName?: string;
|
||||
params?: Params;
|
||||
options?: CoreNavigationOptions;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue