forked from CIT/Vmeda.Online
		
	
						commit
						8a1497ed39
					
				@ -51,16 +51,12 @@ 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') || '';
 | 
			
		||||
 | 
			
		||||
            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') || '';
 | 
			
		||||
 | 
			
		||||
            this.fetchIssuedBadge().finally(() => {
 | 
			
		||||
                this.badgeLoaded = true;
 | 
			
		||||
            });
 | 
			
		||||
        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;
 | 
			
		||||
        this.eventId = CoreNavigator.getRouteNumberParam('id')!;
 | 
			
		||||
        this.syncIcon = CoreConstants.ICON_LOADING;
 | 
			
		||||
 | 
			
		||||
            const eventId = CoreNavigator.getRouteNumberParam('id');
 | 
			
		||||
            if (!eventId) {
 | 
			
		||||
                CoreDomUtils.showErrorModal('Event ID not supplied.');
 | 
			
		||||
                CoreNavigator.back();
 | 
			
		||||
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            this.eventId = eventId;
 | 
			
		||||
            this.syncIcon = CoreConstants.ICON_LOADING;
 | 
			
		||||
 | 
			
		||||
            this.fetchEvent();
 | 
			
		||||
        });
 | 
			
		||||
        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,13 +49,8 @@ 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;
 | 
			
		||||
            });
 | 
			
		||||
        this.fetchData().finally(() => {
 | 
			
		||||
            this.loaded = true;
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -84,42 +84,40 @@ export class AddonMessagesContacts35Page implements OnInit, OnDestroy {
 | 
			
		||||
    /**
 | 
			
		||||
     * Component loaded.
 | 
			
		||||
     */
 | 
			
		||||
    ngOnInit(): void {
 | 
			
		||||
        this.route.queryParams.subscribe(async () => {
 | 
			
		||||
            const discussionUserId = CoreNavigator.getRouteNumberParam('discussionUserId') ||
 | 
			
		||||
                CoreNavigator.getRouteNumberParam('userId') || undefined;
 | 
			
		||||
    async ngOnInit(): Promise<void> {
 | 
			
		||||
        const discussionUserId = CoreNavigator.getRouteNumberParam('discussionUserId') ||
 | 
			
		||||
            CoreNavigator.getRouteNumberParam('userId') || undefined;
 | 
			
		||||
 | 
			
		||||
            if (this.loaded && this.discussionUserId == discussionUserId) {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
        if (this.loaded && this.discussionUserId == discussionUserId) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
            this.discussionUserId = discussionUserId;
 | 
			
		||||
        this.discussionUserId = discussionUserId;
 | 
			
		||||
 | 
			
		||||
            if (this.discussionUserId) {
 | 
			
		||||
                // There is a discussion to load, open the discussion in a new state.
 | 
			
		||||
                this.gotoDiscussion(this.discussionUserId);
 | 
			
		||||
            }
 | 
			
		||||
        if (this.discussionUserId) {
 | 
			
		||||
            // There is a discussion to load, open the discussion in a new state.
 | 
			
		||||
            this.gotoDiscussion(this.discussionUserId);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
            try {
 | 
			
		||||
                await this.fetchData();
 | 
			
		||||
                if (!this.discussionUserId && this.hasContacts && CoreScreen.isTablet) {
 | 
			
		||||
                    let contact: AddonMessagesGetContactsContact | undefined;
 | 
			
		||||
                    for (const x in this.contacts) {
 | 
			
		||||
                        if (this.contacts[x].length > 0) {
 | 
			
		||||
                            contact = this.contacts[x][0];
 | 
			
		||||
                            break;
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    if (contact) {
 | 
			
		||||
                        // Take first and load it.
 | 
			
		||||
                        this.gotoDiscussion(contact.id);
 | 
			
		||||
        try {
 | 
			
		||||
            await this.fetchData();
 | 
			
		||||
            if (!this.discussionUserId && this.hasContacts && CoreScreen.isTablet) {
 | 
			
		||||
                let contact: AddonMessagesGetContactsContact | undefined;
 | 
			
		||||
                for (const x in this.contacts) {
 | 
			
		||||
                    if (this.contacts[x].length > 0) {
 | 
			
		||||
                        contact = this.contacts[x][0];
 | 
			
		||||
                        break;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            } finally {
 | 
			
		||||
                this.loaded = true;
 | 
			
		||||
 | 
			
		||||
                if (contact) {
 | 
			
		||||
                    // Take first and load it.
 | 
			
		||||
                    this.gotoDiscussion(contact.id);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
        } finally {
 | 
			
		||||
            this.loaded = true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
 | 
			
		||||
@ -136,29 +136,18 @@ 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);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            await this.fetchData();
 | 
			
		||||
 | 
			
		||||
            if (!this.discussionUserId && this.discussions.length > 0 && CoreScreen.isTablet) {
 | 
			
		||||
                // Take first and load it.
 | 
			
		||||
                this.gotoDiscussion(this.discussions[0].message!.user);
 | 
			
		||||
            }
 | 
			
		||||
            // When a child page loads this callback is triggered too.
 | 
			
		||||
            this.discussionUserId = CoreNavigator.getRouteNumberParam('userId', { params }) ?? this.discussionUserId;
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        await this.fetchData();
 | 
			
		||||
 | 
			
		||||
        if (!this.discussionUserId && this.discussions.length > 0 && CoreScreen.isTablet) {
 | 
			
		||||
            // 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,34 +268,30 @@ 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;
 | 
			
		||||
            }
 | 
			
		||||
            // 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;
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
            if (this.conversationId || this.discussionUserId) {
 | 
			
		||||
                // There is a discussion to load, open the discussion in a new state.
 | 
			
		||||
                this.gotoConversation(this.conversationId, this.discussionUserId);
 | 
			
		||||
            }
 | 
			
		||||
        await this.fetchData();
 | 
			
		||||
 | 
			
		||||
            await this.fetchData();
 | 
			
		||||
            if (!this.conversationId && !this.discussionUserId && CoreScreen.isTablet) {
 | 
			
		||||
                // Load the first conversation.
 | 
			
		||||
                let conversation: AddonMessagesConversationForList;
 | 
			
		||||
                const expandedOption = this.getExpandedOption();
 | 
			
		||||
        if (!this.selectedConversationId && !this.selectedUserId && CoreScreen.isTablet) {
 | 
			
		||||
            // Load the first conversation.
 | 
			
		||||
            let conversation: AddonMessagesConversationForList;
 | 
			
		||||
            const expandedOption = this.getExpandedOption();
 | 
			
		||||
 | 
			
		||||
                if (expandedOption && expandedOption.conversations.length) {
 | 
			
		||||
                    conversation = expandedOption.conversations[0];
 | 
			
		||||
            if (expandedOption && expandedOption.conversations.length) {
 | 
			
		||||
                conversation = expandedOption.conversations[0];
 | 
			
		||||
 | 
			
		||||
                    if (conversation) {
 | 
			
		||||
                        this.gotoConversation(conversation.id);
 | 
			
		||||
                    }
 | 
			
		||||
                if (conversation) {
 | 
			
		||||
                    this.gotoConversation(conversation.id);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@ -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,
 | 
			
		||||
            },
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -26,7 +26,6 @@ import {
 | 
			
		||||
} from '@angular/router';
 | 
			
		||||
 | 
			
		||||
import { CoreArray } from '@singletons/array';
 | 
			
		||||
import { CoreRedirectGuard } from '@guards/redirect';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Build app routes.
 | 
			
		||||
@ -35,16 +34,7 @@ import { CoreRedirectGuard } from '@guards/redirect';
 | 
			
		||||
 * @return App routes.
 | 
			
		||||
 */
 | 
			
		||||
function buildAppRoutes(injector: Injector): Routes {
 | 
			
		||||
    const appRoutes = CoreArray.flatten(injector.get<Routes[]>(APP_ROUTES, []));
 | 
			
		||||
 | 
			
		||||
    return appRoutes.map(route => {
 | 
			
		||||
        route.canLoad = route.canLoad ?? [];
 | 
			
		||||
        route.canActivate = route.canActivate ?? [];
 | 
			
		||||
        route.canLoad.push(CoreRedirectGuard);
 | 
			
		||||
        route.canActivate.push(CoreRedirectGuard);
 | 
			
		||||
 | 
			
		||||
        return route;
 | 
			
		||||
    });
 | 
			
		||||
    return CoreArray.flatten(injector.get<Routes[]>(APP_ROUTES, []));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 | 
			
		||||
@ -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.
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
@ -4,6 +4,11 @@
 | 
			
		||||
            <ion-back-button [text]="'core.back' | translate"></ion-back-button>
 | 
			
		||||
        </ion-buttons>
 | 
			
		||||
        <ion-title>{{ 'core.contentlinks.chooseaccount' | translate }}</ion-title>
 | 
			
		||||
        <ion-buttons slot="end">
 | 
			
		||||
            <ion-button (click)="closeModal()" [attr.aria-label]="'core.close' | translate">
 | 
			
		||||
                <ion-icon slot="icon-only" name="fas-times" aria-hidden="true"></ion-icon>
 | 
			
		||||
            </ion-button>
 | 
			
		||||
        </ion-buttons>
 | 
			
		||||
    </ion-toolbar>
 | 
			
		||||
</ion-header>
 | 
			
		||||
<ion-content>
 | 
			
		||||
@ -27,11 +32,6 @@
 | 
			
		||||
                    <p>{{site.siteUrl}}</p>
 | 
			
		||||
                </ion-label>
 | 
			
		||||
            </ion-item>
 | 
			
		||||
            <ion-item>
 | 
			
		||||
                <ion-label>
 | 
			
		||||
                    <ion-button expand="block" (click)="cancel()">{{ 'core.login.cancel' | translate }}</ion-button>
 | 
			
		||||
                </ion-label>
 | 
			
		||||
            </ion-item>
 | 
			
		||||
        </ion-list>
 | 
			
		||||
    </core-loading>
 | 
			
		||||
</ion-content>
 | 
			
		||||
@ -12,10 +12,10 @@
 | 
			
		||||
// 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 { CoreSiteBasicInfo, CoreSites } from '@services/sites';
 | 
			
		||||
import { CoreDomUtils } from '@services/utils/dom';
 | 
			
		||||
import { Translate } from '@singletons';
 | 
			
		||||
import { ModalController, Translate } from '@singletons';
 | 
			
		||||
import { CoreContentLinksAction } from '../../services/contentlinks-delegate';
 | 
			
		||||
import { CoreContentLinksHelper } from '../../services/contentlinks-helper';
 | 
			
		||||
import { CoreError } from '@classes/errors/error';
 | 
			
		||||
@ -27,12 +27,13 @@ import { CoreNavigator } from '@services/navigator';
 | 
			
		||||
 * @todo Include routing and testing.
 | 
			
		||||
 */
 | 
			
		||||
@Component({
 | 
			
		||||
    selector: 'page-core-content-links-choose-site',
 | 
			
		||||
    templateUrl: 'choose-site.html',
 | 
			
		||||
    selector: 'core-content-links-choose-site-modal',
 | 
			
		||||
    templateUrl: 'choose-site-modal.html',
 | 
			
		||||
})
 | 
			
		||||
export class CoreContentLinksChooseSitePage implements OnInit {
 | 
			
		||||
export class CoreContentLinksChooseSiteModalComponent implements OnInit {
 | 
			
		||||
 | 
			
		||||
    @Input() url!: string;
 | 
			
		||||
 | 
			
		||||
    url!: string;
 | 
			
		||||
    sites: CoreSiteBasicInfo[] = [];
 | 
			
		||||
    loaded = false;
 | 
			
		||||
    protected action?: CoreContentLinksAction;
 | 
			
		||||
@ -42,12 +43,10 @@ export class CoreContentLinksChooseSitePage implements OnInit {
 | 
			
		||||
     * Component being initialized.
 | 
			
		||||
     */
 | 
			
		||||
    async ngOnInit(): Promise<void> {
 | 
			
		||||
        const url = CoreNavigator.getRouteParam<string>('url');
 | 
			
		||||
        if (!url) {
 | 
			
		||||
            return this.leaveView();
 | 
			
		||||
        if (!this.url) {
 | 
			
		||||
            return this.closeModal();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.url = url;
 | 
			
		||||
        let siteIds: string[] | undefined = [];
 | 
			
		||||
 | 
			
		||||
        try {
 | 
			
		||||
@ -75,25 +74,20 @@ export class CoreContentLinksChooseSitePage implements OnInit {
 | 
			
		||||
            this.sites = await CoreSites.getSites(siteIds);
 | 
			
		||||
        } catch (error) {
 | 
			
		||||
            CoreDomUtils.showErrorModalDefault(error, 'core.contentlinks.errornosites', true);
 | 
			
		||||
            this.leaveView();
 | 
			
		||||
            this.closeModal();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.loaded = true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Cancel.
 | 
			
		||||
     */
 | 
			
		||||
    cancel(): void {
 | 
			
		||||
        this.leaveView();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Perform the action on a certain site.
 | 
			
		||||
     *
 | 
			
		||||
     * @param siteId Site ID.
 | 
			
		||||
     */
 | 
			
		||||
    siteClicked(siteId: string): void {
 | 
			
		||||
    async siteClicked(siteId: string): Promise<void> {
 | 
			
		||||
        await ModalController.dismiss();
 | 
			
		||||
 | 
			
		||||
        if (this.isRootURL) {
 | 
			
		||||
            CoreNavigator.navigateToSiteHome({ siteId });
 | 
			
		||||
        } else if (this.action) {
 | 
			
		||||
@ -102,14 +96,10 @@ export class CoreContentLinksChooseSitePage implements OnInit {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Cancel and leave the view.
 | 
			
		||||
     * Close the modal.
 | 
			
		||||
     */
 | 
			
		||||
    protected async leaveView(): Promise<void> {
 | 
			
		||||
        try {
 | 
			
		||||
            await CoreSites.logout();
 | 
			
		||||
        } finally {
 | 
			
		||||
            await CoreNavigator.navigate('/login/sites', { reset: true });
 | 
			
		||||
        }
 | 
			
		||||
    closeModal(): void {
 | 
			
		||||
        ModalController.dismiss();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -12,26 +12,19 @@
 | 
			
		||||
// See the License for the specific language governing permissions and
 | 
			
		||||
// limitations under the License.
 | 
			
		||||
 | 
			
		||||
import { NgModule } from '@angular/core';
 | 
			
		||||
import { RouterModule, Routes } from '@angular/router';
 | 
			
		||||
 | 
			
		||||
import { CoreSharedModule } from '@/core/shared.module';
 | 
			
		||||
import { CoreContentLinksChooseSitePage } from './choose-site';
 | 
			
		||||
 | 
			
		||||
const routes: Routes = [
 | 
			
		||||
    {
 | 
			
		||||
        path: '',
 | 
			
		||||
        component: CoreContentLinksChooseSitePage,
 | 
			
		||||
    },
 | 
			
		||||
];
 | 
			
		||||
import { NgModule } from '@angular/core';
 | 
			
		||||
import { CoreContentLinksChooseSiteModalComponent } from './choose-site-modal/choose-site-modal';
 | 
			
		||||
 | 
			
		||||
@NgModule({
 | 
			
		||||
    declarations: [
 | 
			
		||||
        CoreContentLinksChooseSitePage,
 | 
			
		||||
        CoreContentLinksChooseSiteModalComponent,
 | 
			
		||||
    ],
 | 
			
		||||
    imports: [
 | 
			
		||||
        RouterModule.forChild(routes),
 | 
			
		||||
        CoreSharedModule,
 | 
			
		||||
    ],
 | 
			
		||||
    exports: [
 | 
			
		||||
        CoreContentLinksChooseSiteModalComponent,
 | 
			
		||||
    ],
 | 
			
		||||
})
 | 
			
		||||
export class CoreContentLinksChooseSitePageModule {}
 | 
			
		||||
export class CoreContentLinksComponentsModule {}
 | 
			
		||||
@ -13,7 +13,7 @@
 | 
			
		||||
// limitations under the License.
 | 
			
		||||
 | 
			
		||||
import { NgModule, Type } from '@angular/core';
 | 
			
		||||
 | 
			
		||||
import { CoreContentLinksComponentsModule } from './components/components.module';
 | 
			
		||||
import { CoreContentLinksDelegateService } from './services/contentlinks-delegate';
 | 
			
		||||
import { CoreContentLinksHelperProvider } from './services/contentlinks-helper';
 | 
			
		||||
 | 
			
		||||
@ -22,5 +22,9 @@ export const CORE_CONTENTLINKS_SERVICES: Type<unknown>[] = [
 | 
			
		||||
    CoreContentLinksHelperProvider,
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
@NgModule({})
 | 
			
		||||
@NgModule({
 | 
			
		||||
    imports: [
 | 
			
		||||
        CoreContentLinksComponentsModule,
 | 
			
		||||
    ],
 | 
			
		||||
})
 | 
			
		||||
export class CoreContentLinksModule {}
 | 
			
		||||
 | 
			
		||||
@ -17,9 +17,10 @@ import { CoreSites } from '@services/sites';
 | 
			
		||||
import { CoreDomUtils } from '@services/utils/dom';
 | 
			
		||||
import { CoreContentLinksDelegate, CoreContentLinksAction } from './contentlinks-delegate';
 | 
			
		||||
import { CoreSite } from '@classes/site';
 | 
			
		||||
import { makeSingleton, Translate } from '@singletons';
 | 
			
		||||
import { makeSingleton, ModalController, Translate } from '@singletons';
 | 
			
		||||
import { CoreNavigator } from '@services/navigator';
 | 
			
		||||
import { Params } from '@angular/router';
 | 
			
		||||
import { CoreContentLinksChooseSiteModalComponent } from '../components/choose-site-modal/choose-site-modal';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Service that provides some features regarding content links.
 | 
			
		||||
@ -56,7 +57,7 @@ export class CoreContentLinksHelperProvider {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get the first valid action in the list of possible actions to do for a URL.
 | 
			
		||||
     * Get the first valid action for a URL.
 | 
			
		||||
     *
 | 
			
		||||
     * @param url URL to handle.
 | 
			
		||||
     * @param courseId Course ID related to the URL. Optional but recommended.
 | 
			
		||||
@ -75,6 +76,16 @@ export class CoreContentLinksHelperProvider {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return this.getFirstValidAction(actions);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get the first valid action in a list of possible actions.
 | 
			
		||||
     *
 | 
			
		||||
     * @param actions Actions.
 | 
			
		||||
     * @return First valid action if any.
 | 
			
		||||
     */
 | 
			
		||||
    getFirstValidAction(actions: CoreContentLinksAction[]): CoreContentLinksAction | undefined {
 | 
			
		||||
        return actions.find((action) => action && action.sites && action.sites.length);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -101,7 +112,15 @@ export class CoreContentLinksHelperProvider {
 | 
			
		||||
     * @todo set correct root.
 | 
			
		||||
     */
 | 
			
		||||
    async goToChooseSite(url: string): Promise<void> {
 | 
			
		||||
        await CoreNavigator.navigate('CoreContentLinksChooseSitePage @todo', { params: { url }, reset: true });
 | 
			
		||||
        const modal = await ModalController.create({
 | 
			
		||||
            component: CoreContentLinksChooseSiteModalComponent,
 | 
			
		||||
            componentProps: {
 | 
			
		||||
                url: url,
 | 
			
		||||
            },
 | 
			
		||||
            cssClass: 'core-modal-fullscreen',
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        await modal.present();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
 | 
			
		||||
@ -311,11 +311,8 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy {
 | 
			
		||||
            this.sectionChanged(sections[0]);
 | 
			
		||||
        } else if (this.initialSectionId || this.initialSectionNumber) {
 | 
			
		||||
            // We have an input indicating the section ID to load. Search the section.
 | 
			
		||||
            const section = sections.find((section) => {
 | 
			
		||||
                if (section.id != this.initialSectionId && (!section.section || section.section != this.initialSectionNumber)) {
 | 
			
		||||
                    return false;
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
            const section = sections.find((section) =>
 | 
			
		||||
                section.id == this.initialSectionId || (section.section && section.section == this.initialSectionNumber));
 | 
			
		||||
 | 
			
		||||
            // Don't load the section if it cannot be viewed by the user.
 | 
			
		||||
            if (section && this.canViewSection(section)) {
 | 
			
		||||
 | 
			
		||||
@ -11,5 +11,5 @@
 | 
			
		||||
    </ion-toolbar>
 | 
			
		||||
</ion-header>
 | 
			
		||||
<ion-content>
 | 
			
		||||
    <core-tabs-outlet [tabs]="tabs" [hideUntil]="loaded"></core-tabs-outlet>
 | 
			
		||||
    <core-tabs-outlet [tabs]="tabs" [hideUntil]="loaded" (ionChange)="tabSelected()"></core-tabs-outlet>
 | 
			
		||||
</ion-content>
 | 
			
		||||
 | 
			
		||||
@ -46,6 +46,8 @@ export class CoreCourseIndexPage implements OnInit, OnDestroy {
 | 
			
		||||
    protected currentPagePath = '';
 | 
			
		||||
    protected selectTabObserver: CoreEventObserver;
 | 
			
		||||
    protected firstTabName?: string;
 | 
			
		||||
    protected module?: CoreCourseWSModule;
 | 
			
		||||
    protected modParams?: Params;
 | 
			
		||||
    protected contentsTab: CoreTabsOutletTab = {
 | 
			
		||||
        page: CONTENTS_PAGE_NAME,
 | 
			
		||||
        title: 'core.course.contents',
 | 
			
		||||
@ -82,8 +84,8 @@ export class CoreCourseIndexPage implements OnInit, OnDestroy {
 | 
			
		||||
        // Get params.
 | 
			
		||||
        this.course = CoreNavigator.getRouteParam('course');
 | 
			
		||||
        this.firstTabName = CoreNavigator.getRouteParam('selectedTab');
 | 
			
		||||
        const module = CoreNavigator.getRouteParam<CoreCourseWSModule>('module');
 | 
			
		||||
        const modParams = CoreNavigator.getRouteParam<Params>('modParams');
 | 
			
		||||
        this.module = CoreNavigator.getRouteParam<CoreCourseWSModule>('module');
 | 
			
		||||
        this.modParams = CoreNavigator.getRouteParam<Params>('modParams');
 | 
			
		||||
 | 
			
		||||
        this.currentPagePath = CoreNavigator.getCurrentPath();
 | 
			
		||||
        this.contentsTab.page = CoreTextUtils.concatenatePaths(this.currentPagePath, this.contentsTab.page);
 | 
			
		||||
@ -93,9 +95,8 @@ export class CoreCourseIndexPage implements OnInit, OnDestroy {
 | 
			
		||||
            sectionNumber: CoreNavigator.getRouteNumberParam('sectionNumber'),
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        if (module) {
 | 
			
		||||
            this.contentsTab.pageParams!.moduleId = module.id;
 | 
			
		||||
            CoreCourseHelper.openModule(module, this.course!.id, this.contentsTab.pageParams!.sectionId, modParams);
 | 
			
		||||
        if (this.module) {
 | 
			
		||||
            this.contentsTab.pageParams!.moduleId = this.module.id;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.tabs.push(this.contentsTab);
 | 
			
		||||
@ -107,6 +108,18 @@ export class CoreCourseIndexPage implements OnInit, OnDestroy {
 | 
			
		||||
        ]);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * A tab was selected.
 | 
			
		||||
     */
 | 
			
		||||
    tabSelected(): void {
 | 
			
		||||
        if (this.module) {
 | 
			
		||||
            // Now that the first tab has been selected we can load the module.
 | 
			
		||||
            CoreCourseHelper.openModule(this.module, this.course!.id, this.contentsTab.pageParams!.sectionId, this.modParams);
 | 
			
		||||
 | 
			
		||||
            delete this.module;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Load course option handlers.
 | 
			
		||||
     *
 | 
			
		||||
 | 
			
		||||
@ -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,
 | 
			
		||||
                });
 | 
			
		||||
            },
 | 
			
		||||
        }];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -17,6 +17,7 @@ import { Routes } from '@angular/router';
 | 
			
		||||
 | 
			
		||||
import { AppRoutingModule } from '@/app/app-routing.module';
 | 
			
		||||
import { CoreLoginHelperProvider } from './services/login-helper';
 | 
			
		||||
import { CoreRedirectGuard } from '@guards/redirect';
 | 
			
		||||
 | 
			
		||||
export const CORE_LOGIN_SERVICES = [
 | 
			
		||||
    CoreLoginHelperProvider,
 | 
			
		||||
@ -26,6 +27,8 @@ const appRoutes: Routes = [
 | 
			
		||||
    {
 | 
			
		||||
        path: 'login',
 | 
			
		||||
        loadChildren: () => import('./login-lazy.module').then(m => m.CoreLoginLazyModule),
 | 
			
		||||
        canActivate: [CoreRedirectGuard],
 | 
			
		||||
        canLoad: [CoreRedirectGuard],
 | 
			
		||||
    },
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -14,7 +14,8 @@
 | 
			
		||||
</ion-header>
 | 
			
		||||
<ion-content>
 | 
			
		||||
    <core-loading [hideUntil]="loaded">
 | 
			
		||||
        <core-tabs-outlet *ngIf="tabs.length > 0" [selectedIndex]="selectedTab" [hideUntil]="loaded" [tabs]="tabs">
 | 
			
		||||
        <core-tabs-outlet *ngIf="tabs.length > 0" [selectedIndex]="selectedTab" [hideUntil]="loaded" [tabs]="tabs"
 | 
			
		||||
            (ionChange)="tabSelected()">
 | 
			
		||||
        </core-tabs-outlet>
 | 
			
		||||
        <ng-container *ngIf="tabs.length == 0">
 | 
			
		||||
            <core-empty-box icon="fas-home" [message]="'core.courses.nocourses' | translate"></core-empty-box>
 | 
			
		||||
 | 
			
		||||
@ -20,6 +20,12 @@ import { CoreEventObserver, CoreEvents } from '@singletons/events';
 | 
			
		||||
import { CoreTabsOutletComponent, CoreTabsOutletTab } from '@components/tabs-outlet/tabs-outlet';
 | 
			
		||||
import { CoreMainMenuHomeDelegate, CoreMainMenuHomeHandlerToDisplay } from '../../services/home-delegate';
 | 
			
		||||
import { CoreUtils } from '@services/utils/utils';
 | 
			
		||||
import { ActivatedRoute } from '@angular/router';
 | 
			
		||||
import { CoreNavigator, CoreRedirectPayload } from '@services/navigator';
 | 
			
		||||
import { CoreCourseHelper } from '@features/course/services/course-helper';
 | 
			
		||||
import { CoreCourse } from '@features/course/services/course';
 | 
			
		||||
import { CoreContentLinksDelegate } from '@features/contentlinks/services/contentlinks-delegate';
 | 
			
		||||
import { CoreContentLinksHelper } from '@features/contentlinks/services/contentlinks-helper';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Page that displays the Home.
 | 
			
		||||
@ -40,11 +46,29 @@ export class CoreMainMenuHomePage implements OnInit {
 | 
			
		||||
 | 
			
		||||
    protected subscription?: Subscription;
 | 
			
		||||
    protected updateSiteObserver?: CoreEventObserver;
 | 
			
		||||
    protected pendingRedirect?: CoreRedirectPayload;
 | 
			
		||||
    protected urlToOpen?: string;
 | 
			
		||||
 | 
			
		||||
    constructor(
 | 
			
		||||
        protected route: ActivatedRoute,
 | 
			
		||||
    ) {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Initialize the component.
 | 
			
		||||
     */
 | 
			
		||||
    ngOnInit(): void {
 | 
			
		||||
        this.route.queryParams.subscribe((params: Partial<CoreRedirectPayload> & { urlToOpen?: string }) => {
 | 
			
		||||
            this.urlToOpen = params.urlToOpen;
 | 
			
		||||
 | 
			
		||||
            if (params.redirectPath) {
 | 
			
		||||
                this.pendingRedirect = {
 | 
			
		||||
                    redirectPath: params.redirectPath,
 | 
			
		||||
                    redirectOptions: params.redirectOptions,
 | 
			
		||||
                };
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this.loadSiteName();
 | 
			
		||||
 | 
			
		||||
        this.subscription = CoreMainMenuHomeDelegate.getHandlersObservable().subscribe((handlers) => {
 | 
			
		||||
@ -111,6 +135,57 @@ export class CoreMainMenuHomePage implements OnInit {
 | 
			
		||||
        this.siteName = CoreSites.getCurrentSite()!.getSiteName();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Handle a redirect.
 | 
			
		||||
     *
 | 
			
		||||
     * @param data Data received.
 | 
			
		||||
     */
 | 
			
		||||
    protected handleRedirect(data: CoreRedirectPayload): void {
 | 
			
		||||
        const params = data.redirectOptions?.params;
 | 
			
		||||
        const coursePathMatches = data.redirectPath.match(/^course\/(\d+)\/?$/);
 | 
			
		||||
 | 
			
		||||
        if (coursePathMatches) {
 | 
			
		||||
            if (!params?.course) {
 | 
			
		||||
                CoreCourseHelper.getAndOpenCourse(Number(coursePathMatches[1]), params);
 | 
			
		||||
            } else {
 | 
			
		||||
                CoreCourse.openCourse(params.course, params);
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            CoreNavigator.navigateToSitePath(data.redirectPath, {
 | 
			
		||||
                ...data.redirectOptions,
 | 
			
		||||
                preferCurrentTab: false,
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Handle a URL to open.
 | 
			
		||||
     *
 | 
			
		||||
     * @param url URL to open.
 | 
			
		||||
     */
 | 
			
		||||
    protected async handleUrlToOpen(url: string): Promise<void> {
 | 
			
		||||
        const actions = await CoreContentLinksDelegate.getActionsFor(url, undefined);
 | 
			
		||||
 | 
			
		||||
        const action = CoreContentLinksHelper.getFirstValidAction(actions);
 | 
			
		||||
        if (action) {
 | 
			
		||||
            action.action(action.sites![0]);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Tab was selected.
 | 
			
		||||
     */
 | 
			
		||||
    tabSelected(): void {
 | 
			
		||||
        if (this.pendingRedirect) {
 | 
			
		||||
            this.handleRedirect(this.pendingRedirect);
 | 
			
		||||
        } else if (this.urlToOpen) {
 | 
			
		||||
            this.handleUrlToOpen(this.urlToOpen);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        delete this.pendingRedirect;
 | 
			
		||||
        delete this.urlToOpen;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * User entered the page.
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
@ -19,14 +19,12 @@ import { BackButtonEvent } from '@ionic/core';
 | 
			
		||||
import { Subscription } from 'rxjs';
 | 
			
		||||
 | 
			
		||||
import { CoreApp } from '@services/app';
 | 
			
		||||
import { CoreSites } from '@services/sites';
 | 
			
		||||
import { CoreTextUtils } from '@services/utils/text';
 | 
			
		||||
import { CoreEvents, CoreEventObserver } from '@singletons/events';
 | 
			
		||||
import { CoreMainMenu, CoreMainMenuProvider } from '../../services/mainmenu';
 | 
			
		||||
import { CoreMainMenuDelegate, CoreMainMenuHandlerToDisplay } from '../../services/mainmenu-delegate';
 | 
			
		||||
import { CoreDomUtils } from '@services/utils/dom';
 | 
			
		||||
import { Translate } from '@singletons';
 | 
			
		||||
import { CoreNavigator, CoreRedirectPayload } from '@services/navigator';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Page that displays the main menu of the app.
 | 
			
		||||
@ -47,9 +45,6 @@ export class CoreMainMenuPage implements OnInit, OnDestroy {
 | 
			
		||||
    morePageName = CoreMainMenuProvider.MORE_PAGE_NAME;
 | 
			
		||||
 | 
			
		||||
    protected subscription?: Subscription;
 | 
			
		||||
    protected redirectObs?: CoreEventObserver;
 | 
			
		||||
    protected pendingRedirect?: CoreRedirectPayload;
 | 
			
		||||
    protected urlToOpen?: string;
 | 
			
		||||
    protected keyboardObserver?: CoreEventObserver;
 | 
			
		||||
    protected resizeFunction: () => void;
 | 
			
		||||
    protected backButtonFunction: (event: BackButtonEvent) => void;
 | 
			
		||||
@ -72,24 +67,6 @@ export class CoreMainMenuPage implements OnInit, OnDestroy {
 | 
			
		||||
     * Initialize the component.
 | 
			
		||||
     */
 | 
			
		||||
    ngOnInit(): void {
 | 
			
		||||
        // @TODO this should be handled by route guards and can be removed
 | 
			
		||||
        if (!CoreSites.isLoggedIn()) {
 | 
			
		||||
            CoreNavigator.navigate('/login/init', { reset: true });
 | 
			
		||||
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.route.queryParams.subscribe((params: Partial<CoreRedirectPayload> & { urlToOpen?: string }) => {
 | 
			
		||||
            if (params.redirectPath) {
 | 
			
		||||
                this.pendingRedirect = {
 | 
			
		||||
                    redirectPath: params.redirectPath,
 | 
			
		||||
                    redirectParams: params.redirectParams,
 | 
			
		||||
                };
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            this.urlToOpen = params.urlToOpen;
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this.showTabs = true;
 | 
			
		||||
 | 
			
		||||
        this.subscription = CoreMainMenuDelegate.getHandlersObservable().subscribe((handlers) => {
 | 
			
		||||
@ -97,16 +74,6 @@ export class CoreMainMenuPage implements OnInit, OnDestroy {
 | 
			
		||||
            this.allHandlers = handlers.filter((handler) => !handler.onlyInMore);
 | 
			
		||||
 | 
			
		||||
            this.initHandlers();
 | 
			
		||||
 | 
			
		||||
            if (this.loaded && this.pendingRedirect) {
 | 
			
		||||
                // Wait for tabs to be initialized and then handle the redirect.
 | 
			
		||||
                setTimeout(() => {
 | 
			
		||||
                    if (this.pendingRedirect) {
 | 
			
		||||
                        this.handleRedirect(this.pendingRedirect);
 | 
			
		||||
                        delete this.pendingRedirect;
 | 
			
		||||
                    }
 | 
			
		||||
                });
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        window.addEventListener('resize', this.resizeFunction);
 | 
			
		||||
@ -158,18 +125,6 @@ export class CoreMainMenuPage implements OnInit, OnDestroy {
 | 
			
		||||
            this.tabs.sort((a, b) => (b.priority || 0) - (a.priority || 0));
 | 
			
		||||
 | 
			
		||||
            this.loaded = CoreMainMenuDelegate.areHandlersLoaded();
 | 
			
		||||
 | 
			
		||||
            if (this.loaded && this.mainTabs && !this.mainTabs.getSelected()) {
 | 
			
		||||
                // Select the first tab.
 | 
			
		||||
                setTimeout(() => {
 | 
			
		||||
                    this.mainTabs!.select(this.tabs[0]?.page || this.morePageName);
 | 
			
		||||
                });
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (this.urlToOpen) {
 | 
			
		||||
            // There's a content link to open.
 | 
			
		||||
            // @todo: Treat URL.
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -189,36 +144,11 @@ export class CoreMainMenuPage implements OnInit, OnDestroy {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Handle a redirect.
 | 
			
		||||
     *
 | 
			
		||||
     * @param data Data received.
 | 
			
		||||
     */
 | 
			
		||||
    protected handleRedirect(data: CoreRedirectPayload): void {
 | 
			
		||||
        // Check if the redirect page is the root page of any of the tabs.
 | 
			
		||||
        const i = this.tabs.findIndex((tab) => tab.page == data.redirectPath);
 | 
			
		||||
 | 
			
		||||
        if (i >= 0) {
 | 
			
		||||
            // Tab found. Open it with the params.
 | 
			
		||||
            CoreNavigator.navigate(data.redirectPath, {
 | 
			
		||||
                params: data.redirectParams,
 | 
			
		||||
                animated: false,
 | 
			
		||||
            });
 | 
			
		||||
        } else {
 | 
			
		||||
            // Tab not found, use a phantom tab.
 | 
			
		||||
            // @todo
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Force change detection, otherwise sometimes the tab was selected before the params were applied.
 | 
			
		||||
        this.changeDetector.detectChanges();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Page destroyed.
 | 
			
		||||
     */
 | 
			
		||||
    ngOnDestroy(): void {
 | 
			
		||||
        this.subscription?.unsubscribe();
 | 
			
		||||
        this.redirectObs?.off();
 | 
			
		||||
        window.removeEventListener('resize', this.resizeFunction);
 | 
			
		||||
        document.removeEventListener('ionBackButton', this.backButtonFunction);
 | 
			
		||||
        this.keyboardObserver?.off();
 | 
			
		||||
 | 
			
		||||
@ -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,52 +41,48 @@ 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.getRedirect();
 | 
			
		||||
        const redirect = CoreApp.consumeMemoryRedirect();
 | 
			
		||||
 | 
			
		||||
        if (!redirect) {
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        try {
 | 
			
		||||
            // Only accept the redirect if it was stored less than 20 seconds ago.
 | 
			
		||||
            if (!redirect.timemodified || Date.now() - redirect.timemodified < 20000) {
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
        // Only accept the redirect if it was stored less than 20 seconds ago.
 | 
			
		||||
        if (!redirect.timemodified || Date.now() - redirect.timemodified > 20000) {
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
            // Redirect to site path.
 | 
			
		||||
            if (redirect.siteId && redirect.siteId !== CoreConstants.NO_SITE_ID) {
 | 
			
		||||
                const loggedIn = await CoreSites.loadSite(
 | 
			
		||||
                    redirect.siteId,
 | 
			
		||||
                    redirect.page,
 | 
			
		||||
                    redirect.params,
 | 
			
		||||
                );
 | 
			
		||||
                const route = Router.parseUrl('/main');
 | 
			
		||||
 | 
			
		||||
                route.queryParams = {
 | 
			
		||||
                    redirectPath: redirect.page,
 | 
			
		||||
                    redirectParams: redirect.params,
 | 
			
		||||
                };
 | 
			
		||||
 | 
			
		||||
                return loggedIn ? route : true;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Abort redirect.
 | 
			
		||||
            if (!redirect.page) {
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Redirect to non-site path.
 | 
			
		||||
            const route = Router.parseUrl(redirect.page);
 | 
			
		||||
        // Redirect to site path.
 | 
			
		||||
        if (redirect.siteId && redirect.siteId !== CoreConstants.NO_SITE_ID) {
 | 
			
		||||
            const loggedIn = await CoreSites.loadSite(
 | 
			
		||||
                redirect.siteId,
 | 
			
		||||
                redirect.page,
 | 
			
		||||
                redirect.options,
 | 
			
		||||
            );
 | 
			
		||||
            const route = Router.parseUrl('/main/home');
 | 
			
		||||
 | 
			
		||||
            route.queryParams = {
 | 
			
		||||
                redirectPath: redirect.page,
 | 
			
		||||
                redirectParams: redirect.params,
 | 
			
		||||
            };
 | 
			
		||||
                redirectOptions: redirect.options,
 | 
			
		||||
            } as CoreRedirectPayload;
 | 
			
		||||
 | 
			
		||||
            return route;
 | 
			
		||||
        } finally {
 | 
			
		||||
            CoreApp.forgetRedirect();
 | 
			
		||||
            return loggedIn ? route : true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Abort redirect.
 | 
			
		||||
        if (!redirect.page) {
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Redirect to non-site path.
 | 
			
		||||
        const route = Router.parseUrl(redirect.page);
 | 
			
		||||
 | 
			
		||||
        route.queryParams = {
 | 
			
		||||
            redirectPath: redirect.page,
 | 
			
		||||
            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.
 | 
			
		||||
@ -549,6 +549,19 @@ export class CoreAppProvider {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Retrieve and forget redirect data.
 | 
			
		||||
     *
 | 
			
		||||
     * @return Redirect data if any.
 | 
			
		||||
     */
 | 
			
		||||
    consumeMemoryRedirect(): CoreRedirectData | null {
 | 
			
		||||
        const redirect = this.getRedirect();
 | 
			
		||||
 | 
			
		||||
        this.forgetRedirect();
 | 
			
		||||
 | 
			
		||||
        return redirect;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Forget redirect data.
 | 
			
		||||
     */
 | 
			
		||||
@ -559,7 +572,7 @@ export class CoreAppProvider {
 | 
			
		||||
    /**
 | 
			
		||||
     * Retrieve redirect data.
 | 
			
		||||
     *
 | 
			
		||||
     * @return Object with siteid, state, params and timemodified.
 | 
			
		||||
     * @return Redirect data if any.
 | 
			
		||||
     */
 | 
			
		||||
    getRedirect(): CoreRedirectData | null {
 | 
			
		||||
        return this.redirect || null;
 | 
			
		||||
@ -570,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(),
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
@ -658,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.
 | 
			
		||||
 | 
			
		||||
@ -30,6 +30,7 @@ import { makeSingleton, NavController, Router } from '@singletons';
 | 
			
		||||
import { CoreScreen } from './screen';
 | 
			
		||||
import { filter } from 'rxjs/operators';
 | 
			
		||||
import { CoreApp } from './app';
 | 
			
		||||
import { CoreSitePlugins } from '@features/siteplugins/services/siteplugins';
 | 
			
		||||
 | 
			
		||||
const DEFAULT_MAIN_MENU_TAB = CoreMainMenuHomeHandlerService.PAGE_NAME;
 | 
			
		||||
 | 
			
		||||
@ -38,7 +39,7 @@ const DEFAULT_MAIN_MENU_TAB = CoreMainMenuHomeHandlerService.PAGE_NAME;
 | 
			
		||||
 */
 | 
			
		||||
export type CoreRedirectPayload = {
 | 
			
		||||
    redirectPath: string;
 | 
			
		||||
    redirectParams?: Params;
 | 
			
		||||
    redirectOptions?: CoreNavigationOptions;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@ -49,6 +50,11 @@ export type CoreNavigationOptions = {
 | 
			
		||||
    params?: Params;
 | 
			
		||||
    reset?: boolean;
 | 
			
		||||
    preferCurrentTab?: boolean; // Default true.
 | 
			
		||||
    nextNavigation?: {
 | 
			
		||||
        path: string;
 | 
			
		||||
        isSitePath?: boolean;
 | 
			
		||||
        options?: CoreNavigationOptions;
 | 
			
		||||
    };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@ -148,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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -208,7 +222,14 @@ export class CoreNavigatorService {
 | 
			
		||||
 | 
			
		||||
        // If we are logged into a different site, log out first.
 | 
			
		||||
        if (CoreSites.isLoggedIn() && CoreSites.getCurrentSiteId() !== siteId) {
 | 
			
		||||
            // @todo: Check site plugins and store redirect.
 | 
			
		||||
            if (CoreSitePlugins.hasSitePluginsLoaded) {
 | 
			
		||||
                // The site has site plugins so the app will be restarted. Store the data and logout.
 | 
			
		||||
                CoreApp.storeRedirect(siteId, path, options || {});
 | 
			
		||||
 | 
			
		||||
                await CoreSites.logout();
 | 
			
		||||
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            await CoreSites.logout();
 | 
			
		||||
        }
 | 
			
		||||
@ -442,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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user