forked from CIT/Vmeda.Online
		
	
						commit
						75cedafa33
					
				@ -237,6 +237,7 @@
 | 
				
			|||||||
  "addon.messages.blocknoncontacts": "message",
 | 
					  "addon.messages.blocknoncontacts": "message",
 | 
				
			||||||
  "addon.messages.blockuser": "message",
 | 
					  "addon.messages.blockuser": "message",
 | 
				
			||||||
  "addon.messages.blockuserconfirm": "message",
 | 
					  "addon.messages.blockuserconfirm": "message",
 | 
				
			||||||
 | 
					  "addon.messages.cantblockuser": "message",
 | 
				
			||||||
  "addon.messages.contactableprivacy": "message",
 | 
					  "addon.messages.contactableprivacy": "message",
 | 
				
			||||||
  "addon.messages.contactableprivacy_coursemember": "message",
 | 
					  "addon.messages.contactableprivacy_coursemember": "message",
 | 
				
			||||||
  "addon.messages.contactableprivacy_onlycontacts": "message",
 | 
					  "addon.messages.contactableprivacy_onlycontacts": "message",
 | 
				
			||||||
 | 
				
			|||||||
@ -7,6 +7,7 @@
 | 
				
			|||||||
    "blocknoncontacts": "Prevent non-contacts from messaging me",
 | 
					    "blocknoncontacts": "Prevent non-contacts from messaging me",
 | 
				
			||||||
    "blockuser": "Block user",
 | 
					    "blockuser": "Block user",
 | 
				
			||||||
    "blockuserconfirm": "Are you sure you want to block {{$a}}?",
 | 
					    "blockuserconfirm": "Are you sure you want to block {{$a}}?",
 | 
				
			||||||
 | 
					    "cantblockuser": "You can't block {{$a}} because they have a role with permission to message all users.",
 | 
				
			||||||
    "contactableprivacy": "Accept messages from:",
 | 
					    "contactableprivacy": "Accept messages from:",
 | 
				
			||||||
    "contactableprivacy_coursemember": "My contacts and anyone in my courses",
 | 
					    "contactableprivacy_coursemember": "My contacts and anyone in my courses",
 | 
				
			||||||
    "contactableprivacy_onlycontacts": "My contacts only",
 | 
					    "contactableprivacy_onlycontacts": "My contacts only",
 | 
				
			||||||
 | 
				
			|||||||
@ -1446,6 +1446,12 @@ export class AddonMessagesDiscussionPage implements OnInit, OnDestroy, AfterView
 | 
				
			|||||||
            throw new CoreError('No member selected to be blocked.');
 | 
					            throw new CoreError('No member selected to be blocked.');
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (this.otherMember.canmessageevenifblocked) {
 | 
				
			||||||
 | 
					            CoreDomUtils.showErrorModal(Translate.instant('addon.messages.cantblockuser', { $a: this.otherMember.fullname }));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const template = Translate.instant('addon.messages.blockuserconfirm', { $a: this.otherMember.fullname });
 | 
					        const template = Translate.instant('addon.messages.blockuserconfirm', { $a: this.otherMember.fullname });
 | 
				
			||||||
        const okText = Translate.instant('addon.messages.blockuser');
 | 
					        const okText = Translate.instant('addon.messages.blockuser');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -407,8 +407,8 @@ export class AddonModAssignIndexComponent extends CoreCourseModuleMainActivityCo
 | 
				
			|||||||
     *
 | 
					     *
 | 
				
			||||||
     * @return Promise resolved when done.
 | 
					     * @return Promise resolved when done.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    protected async sync(): Promise<void> {
 | 
					    protected sync(): Promise<AddonModAssignSyncResult> {
 | 
				
			||||||
        await AddonModAssignSync.syncAssign(this.assign!.id);
 | 
					        return AddonModAssignSync.syncAssign(this.assign!.id);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
 | 
				
			|||||||
@ -235,12 +235,12 @@ export class AddonModAssignEditPage implements OnInit, OnDestroy, CanLeave {
 | 
				
			|||||||
     * @param inputData The input data.
 | 
					     * @param inputData The input data.
 | 
				
			||||||
     * @return Promise resolved with the data to submit.
 | 
					     * @return Promise resolved with the data to submit.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    protected prepareSubmissionData(inputData: CoreFormFields): Promise<AddonModAssignSavePluginData> {
 | 
					    protected async prepareSubmissionData(inputData: CoreFormFields): Promise<AddonModAssignSavePluginData> {
 | 
				
			||||||
        // If there's offline data, always save it in offline.
 | 
					        // If there's offline data, always save it in offline.
 | 
				
			||||||
        this.saveOffline = this.hasOffline;
 | 
					        this.saveOffline = this.hasOffline;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            return AddonModAssignHelper.prepareSubmissionPluginData(
 | 
					            return await AddonModAssignHelper.prepareSubmissionPluginData(
 | 
				
			||||||
                this.assign!,
 | 
					                this.assign!,
 | 
				
			||||||
                this.userSubmission,
 | 
					                this.userSubmission,
 | 
				
			||||||
                inputData,
 | 
					                inputData,
 | 
				
			||||||
@ -251,7 +251,7 @@ export class AddonModAssignEditPage implements OnInit, OnDestroy, CanLeave {
 | 
				
			|||||||
                // Cannot submit in online, prepare for offline usage.
 | 
					                // Cannot submit in online, prepare for offline usage.
 | 
				
			||||||
                this.saveOffline = true;
 | 
					                this.saveOffline = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                return AddonModAssignHelper.prepareSubmissionPluginData(
 | 
					                return await AddonModAssignHelper.prepareSubmissionPluginData(
 | 
				
			||||||
                    this.assign!,
 | 
					                    this.assign!,
 | 
				
			||||||
                    this.userSubmission,
 | 
					                    this.userSubmission,
 | 
				
			||||||
                    inputData,
 | 
					                    inputData,
 | 
				
			||||||
 | 
				
			|||||||
@ -514,8 +514,8 @@ export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComp
 | 
				
			|||||||
     *
 | 
					     *
 | 
				
			||||||
     * @return Promise resolved when done.
 | 
					     * @return Promise resolved when done.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    protected async sync(): Promise<void> {
 | 
					    protected sync(): Promise<AddonModDataSyncResult> {
 | 
				
			||||||
        await AddonModDataPrefetchHandler.sync(this.module, this.courseId);
 | 
					        return AddonModDataPrefetchHandler.sync(this.module, this.courseId);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
 | 
				
			|||||||
@ -233,8 +233,8 @@ export class AddonModSurveyIndexComponent extends CoreCourseModuleMainActivityCo
 | 
				
			|||||||
     *
 | 
					     *
 | 
				
			||||||
     * @return Promise resolved when done.
 | 
					     * @return Promise resolved when done.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    protected async sync(): Promise<void> {
 | 
					    protected sync(): Promise<AddonModSurveySyncResult> {
 | 
				
			||||||
        await AddonModSurveySync.syncSurvey(this.survey!.id, this.currentUserId);
 | 
					        return AddonModSurveySync.syncSurvey(this.survey!.id, this.currentUserId);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
 | 
				
			|||||||
@ -224,11 +224,17 @@ export class AppComponent implements OnInit, AfterViewInit {
 | 
				
			|||||||
        document.addEventListener('ionBackButton', (event: BackButtonEvent) => {
 | 
					        document.addEventListener('ionBackButton', (event: BackButtonEvent) => {
 | 
				
			||||||
            // This callback should have the lowest priority in the app.
 | 
					            // This callback should have the lowest priority in the app.
 | 
				
			||||||
            event.detail.register(-100, async () => {
 | 
					            event.detail.register(-100, async () => {
 | 
				
			||||||
 | 
					                const initialPath = CoreNavigator.getCurrentPath();
 | 
				
			||||||
 | 
					                if (initialPath.startsWith('/main/')) {
 | 
				
			||||||
 | 
					                    // Main menu has its own callback to handle back. If this callback is called it means we should exit app.
 | 
				
			||||||
 | 
					                    CoreApp.closeApp();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    return;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                // This callback can be called at the same time as Ionic's back navigation callback.
 | 
					                // This callback can be called at the same time as Ionic's back navigation callback.
 | 
				
			||||||
                // Check if the path changes due to the back navigation handler, to know if we're at root level.
 | 
					                // Check if the path changes due to the back navigation handler, to know if we're at root level.
 | 
				
			||||||
                // Ionic doc recommends IonRouterOutlet.canGoBack, but there's no easy way to get the current outlet from here.
 | 
					                // Ionic doc recommends IonRouterOutlet.canGoBack, but there's no easy way to get the current outlet from here.
 | 
				
			||||||
                const initialPath = CoreNavigator.getCurrentPath();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                // The path seems to change immediately (0 ms timeout), but use 50ms just in case.
 | 
					                // The path seems to change immediately (0 ms timeout), but use 50ms just in case.
 | 
				
			||||||
                await CoreUtils.wait(50);
 | 
					                await CoreUtils.wait(50);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -238,8 +244,7 @@ export class AppComponent implements OnInit, AfterViewInit {
 | 
				
			|||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                // Quit the app.
 | 
					                // Quit the app.
 | 
				
			||||||
                const nav = <any> window.navigator; // eslint-disable-line @typescript-eslint/no-explicit-any
 | 
					                CoreApp.closeApp();
 | 
				
			||||||
                nav.app?.exitApp();
 | 
					 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -7,7 +7,7 @@
 | 
				
			|||||||
    <ion-item *ngIf="model[modelValueName]">
 | 
					    <ion-item *ngIf="model[modelValueName]">
 | 
				
			||||||
        <ion-label color="success">{{ 'core.answered' | translate }}</ion-label>
 | 
					        <ion-label color="success">{{ 'core.answered' | translate }}</ion-label>
 | 
				
			||||||
    </ion-item>
 | 
					    </ion-item>
 | 
				
			||||||
    <ion-item *ngIf="expired">
 | 
					    <ion-item *ngIf="expired" class="ion-text-wrap">
 | 
				
			||||||
        <ion-label color="danger">{{ 'core.login.recaptchaexpired' | translate }}</ion-label>
 | 
					        <ion-label color="danger">{{ 'core.login.recaptchaexpired' | translate }}</ion-label>
 | 
				
			||||||
    </ion-item>
 | 
					    </ion-item>
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
 | 
				
			|||||||
@ -87,8 +87,7 @@ export class CoreRecaptchaComponent implements OnInit {
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (event.data.action == 'expired') {
 | 
					            if (event.data.action == 'expired') {
 | 
				
			||||||
                this.expired = true;
 | 
					                this.expireRecaptchaAnswer();
 | 
				
			||||||
                this.model![this.modelValueName] = '';
 | 
					 | 
				
			||||||
            } else if (event.data.action == 'callback') {
 | 
					            } else if (event.data.action == 'callback') {
 | 
				
			||||||
                this.expired = false;
 | 
					                this.expired = false;
 | 
				
			||||||
                this.model![this.modelValueName] = event.data.value;
 | 
					                this.model![this.modelValueName] = event.data.value;
 | 
				
			||||||
@ -101,4 +100,12 @@ export class CoreRecaptchaComponent implements OnInit {
 | 
				
			|||||||
        });
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Expire the recaptcha answer.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    expireRecaptchaAnswer(): void {
 | 
				
			||||||
 | 
					        this.expired = true;
 | 
				
			||||||
 | 
					        this.model![this.modelValueName] = '';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -14,6 +14,8 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import { Component, OnInit, OnDestroy, ViewChild, ElementRef } from '@angular/core';
 | 
					import { Component, OnInit, OnDestroy, ViewChild, ElementRef } from '@angular/core';
 | 
				
			||||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
 | 
					import { FormBuilder, FormGroup, Validators } from '@angular/forms';
 | 
				
			||||||
 | 
					import { Subscription } from 'rxjs';
 | 
				
			||||||
 | 
					import { debounceTime } from 'rxjs/operators';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { CoreApp } from '@services/app';
 | 
					import { CoreApp } from '@services/app';
 | 
				
			||||||
import { CoreSites } from '@services/sites';
 | 
					import { CoreSites } from '@services/sites';
 | 
				
			||||||
@ -36,7 +38,7 @@ import { CoreForms } from '@singletons/form';
 | 
				
			|||||||
})
 | 
					})
 | 
				
			||||||
export class CoreLoginCredentialsPage implements OnInit, OnDestroy {
 | 
					export class CoreLoginCredentialsPage implements OnInit, OnDestroy {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @ViewChild('credentialsForm') formElement?: ElementRef;
 | 
					    @ViewChild('credentialsForm') formElement?: ElementRef<HTMLFormElement>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    credForm!: FormGroup;
 | 
					    credForm!: FormGroup;
 | 
				
			||||||
    siteUrl!: string;
 | 
					    siteUrl!: string;
 | 
				
			||||||
@ -57,6 +59,7 @@ export class CoreLoginCredentialsPage implements OnInit, OnDestroy {
 | 
				
			|||||||
    protected viewLeft = false;
 | 
					    protected viewLeft = false;
 | 
				
			||||||
    protected siteId?: string;
 | 
					    protected siteId?: string;
 | 
				
			||||||
    protected urlToOpen?: string;
 | 
					    protected urlToOpen?: string;
 | 
				
			||||||
 | 
					    protected valueChangeSubscription?: Subscription;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constructor(
 | 
					    constructor(
 | 
				
			||||||
        protected fb: FormBuilder,
 | 
					        protected fb: FormBuilder,
 | 
				
			||||||
@ -96,6 +99,28 @@ export class CoreLoginCredentialsPage implements OnInit, OnDestroy {
 | 
				
			|||||||
            this.siteChecked = true;
 | 
					            this.siteChecked = true;
 | 
				
			||||||
            this.pageLoaded = true;
 | 
					            this.pageLoaded = true;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (CoreApp.isIOS()) {
 | 
				
			||||||
 | 
					            // Make iOS auto-fill work. The field that isn't focused doesn't get updated, do it manually.
 | 
				
			||||||
 | 
					            // Debounce it to prevent triggering this function too often when the user is typing.
 | 
				
			||||||
 | 
					            this.valueChangeSubscription = this.credForm.valueChanges.pipe(debounceTime(1000)).subscribe((changes) => {
 | 
				
			||||||
 | 
					                if (!this.formElement || !this.formElement.nativeElement) {
 | 
				
			||||||
 | 
					                    return;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                const usernameInput = this.formElement.nativeElement.querySelector<HTMLInputElement>('input[name="username"]');
 | 
				
			||||||
 | 
					                const passwordInput = this.formElement.nativeElement.querySelector<HTMLInputElement>('input[name="password"]');
 | 
				
			||||||
 | 
					                const usernameValue = usernameInput?.value;
 | 
				
			||||||
 | 
					                const passwordValue = passwordInput?.value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                if (usernameValue !== undefined && usernameValue !== changes.username) {
 | 
				
			||||||
 | 
					                    this.credForm.get('username')?.setValue(usernameValue);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                if (passwordValue !== undefined && passwordValue !== changes.password) {
 | 
				
			||||||
 | 
					                    this.credForm.get('password')?.setValue(passwordValue);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
@ -307,6 +332,7 @@ export class CoreLoginCredentialsPage implements OnInit, OnDestroy {
 | 
				
			|||||||
    ngOnDestroy(): void {
 | 
					    ngOnDestroy(): void {
 | 
				
			||||||
        this.viewLeft = true;
 | 
					        this.viewLeft = true;
 | 
				
			||||||
        CoreEvents.trigger(CoreEvents.LOGIN_SITE_UNCHECKED, { config: this.siteConfig }, this.siteId);
 | 
					        CoreEvents.trigger(CoreEvents.LOGIN_SITE_UNCHECKED, { config: this.siteConfig }, this.siteId);
 | 
				
			||||||
 | 
					        this.valueChangeSubscription?.unsubscribe();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -33,6 +33,7 @@ import {
 | 
				
			|||||||
} from '@features/login/services/login-helper';
 | 
					} from '@features/login/services/login-helper';
 | 
				
			||||||
import { CoreNavigator } from '@services/navigator';
 | 
					import { CoreNavigator } from '@services/navigator';
 | 
				
			||||||
import { CoreForms } from '@singletons/form';
 | 
					import { CoreForms } from '@singletons/form';
 | 
				
			||||||
 | 
					import { CoreRecaptchaComponent } from '@components/recaptcha/recaptcha';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Page to signup using email.
 | 
					 * Page to signup using email.
 | 
				
			||||||
@ -45,6 +46,7 @@ import { CoreForms } from '@singletons/form';
 | 
				
			|||||||
export class CoreLoginEmailSignupPage implements OnInit {
 | 
					export class CoreLoginEmailSignupPage implements OnInit {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @ViewChild(IonContent) content?: IonContent;
 | 
					    @ViewChild(IonContent) content?: IonContent;
 | 
				
			||||||
 | 
					    @ViewChild(CoreRecaptchaComponent) recaptchaComponent?: CoreRecaptchaComponent;
 | 
				
			||||||
    @ViewChild('ageForm') ageFormElement?: ElementRef;
 | 
					    @ViewChild('ageForm') ageFormElement?: ElementRef;
 | 
				
			||||||
    @ViewChild('signupFormEl') signupFormElement?: ElementRef;
 | 
					    @ViewChild('signupFormEl') signupFormElement?: ElementRef;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -341,9 +343,12 @@ export class CoreLoginEmailSignupPage implements OnInit {
 | 
				
			|||||||
                CoreDomUtils.showAlert(Translate.instant('core.success'), message);
 | 
					                CoreDomUtils.showAlert(Translate.instant('core.success'), message);
 | 
				
			||||||
                CoreNavigator.back();
 | 
					                CoreNavigator.back();
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                if (result.warnings && result.warnings.length) {
 | 
					                this.recaptchaComponent?.expireRecaptchaAnswer();
 | 
				
			||||||
                    let error = result.warnings[0].message;
 | 
					
 | 
				
			||||||
                    if (error == 'incorrect-captcha-sol') {
 | 
					                const warning = result.warnings?.[0];
 | 
				
			||||||
 | 
					                if (warning) {
 | 
				
			||||||
 | 
					                    let error = warning.message;
 | 
				
			||||||
 | 
					                    if (error == 'incorrect-captcha-sol' || (!error && warning.item == 'recaptcharesponse')) {
 | 
				
			||||||
                        error = Translate.instant('core.login.recaptchaincorrect');
 | 
					                        error = Translate.instant('core.login.recaptchaincorrect');
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -661,9 +661,7 @@ export class CoreLoginHelperProvider {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        // Always open it in browser because the user might have the session stored in there.
 | 
					        // Always open it in browser because the user might have the session stored in there.
 | 
				
			||||||
        CoreUtils.openInBrowser(loginUrl);
 | 
					        CoreUtils.openInBrowser(loginUrl);
 | 
				
			||||||
 | 
					        CoreApp.closeApp();
 | 
				
			||||||
        const nav = <any> window.navigator; // eslint-disable-line @typescript-eslint/no-explicit-any
 | 
					 | 
				
			||||||
        nav.app?.exitApp();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return true;
 | 
					        return true;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -695,9 +693,7 @@ export class CoreLoginHelperProvider {
 | 
				
			|||||||
            });
 | 
					            });
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            CoreUtils.openInBrowser(loginUrl);
 | 
					            CoreUtils.openInBrowser(loginUrl);
 | 
				
			||||||
 | 
					            CoreApp.closeApp();
 | 
				
			||||||
            const nav = <any> window.navigator; // eslint-disable-line @typescript-eslint/no-explicit-any
 | 
					 | 
				
			||||||
            nav.app?.exitApp();
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -226,16 +226,10 @@ export class CoreMainMenuPage implements OnInit, OnDestroy {
 | 
				
			|||||||
        // Use a priority lower than 0 (navigation).
 | 
					        // Use a priority lower than 0 (navigation).
 | 
				
			||||||
        event.detail.register(-10, async (processNextHandler: () => void) => {
 | 
					        event.detail.register(-10, async (processNextHandler: () => void) => {
 | 
				
			||||||
            // This callback can be called at the same time as Ionic's back navigation callback.
 | 
					            // This callback can be called at the same time as Ionic's back navigation callback.
 | 
				
			||||||
            // Check if the path changes due to the back navigation handler, to know if we're at root level of the tab.
 | 
					            // Check if user is already at the root of a tab.
 | 
				
			||||||
            // Ionic doc recommends IonRouterOutlet.canGoBack, but there's no easy way to get the current outlet from here.
 | 
					            const mainMenuRootRoute = CoreNavigator.getCurrentRoute({ routeData: { isMainMenuRoot: true } });
 | 
				
			||||||
            const initialPath = CoreNavigator.getCurrentPath();
 | 
					            if (!mainMenuRootRoute) {
 | 
				
			||||||
 | 
					                return; // Not at root level, let Ionic handle the navigation.
 | 
				
			||||||
            // The path seems to change immediately (0 ms timeout), but use 50ms just in case.
 | 
					 | 
				
			||||||
            await CoreUtils.wait(50);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (CoreNavigator.getCurrentPath() != initialPath) {
 | 
					 | 
				
			||||||
                // Ionic has navigated back, nothing else to do.
 | 
					 | 
				
			||||||
                return;
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // No back navigation, already at root level. Check if we should change tab.
 | 
					            // No back navigation, already at root level. Check if we should change tab.
 | 
				
			||||||
 | 
				
			|||||||
@ -30,6 +30,9 @@ import { buildTabMainRoutes } from '@features/mainmenu/mainmenu-tab-routing.modu
 | 
				
			|||||||
            deps: [Injector],
 | 
					            deps: [Injector],
 | 
				
			||||||
            useFactory: (injector: Injector) => buildTabMainRoutes(injector, {
 | 
					            useFactory: (injector: Injector) => buildTabMainRoutes(injector, {
 | 
				
			||||||
                component: CoreMainMenuMorePage,
 | 
					                component: CoreMainMenuMorePage,
 | 
				
			||||||
 | 
					                data: {
 | 
				
			||||||
 | 
					                    isMainMenuRoot: true,
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
            }),
 | 
					            }),
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
 | 
				
			|||||||
@ -562,6 +562,14 @@ export class CoreAppProvider {
 | 
				
			|||||||
        return redirect;
 | 
					        return redirect;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Close the app.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    closeApp(): void {
 | 
				
			||||||
 | 
					        const nav = <any> window.navigator; // eslint-disable-line @typescript-eslint/no-explicit-any
 | 
				
			||||||
 | 
					        nav.app?.exitApp();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Forget redirect data.
 | 
					     * Forget redirect data.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user