forked from CIT/Vmeda.Online
		
	MOBILE-3708 android: Handle back button in tabs
This commit is contained in:
		
							parent
							
								
									81bf906fef
								
							
						
					
					
						commit
						3d80e57402
					
				@ -115,6 +115,8 @@ export class AppComponent implements OnInit, AfterViewInit {
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this.onPlatformReady();
 | 
			
		||||
 | 
			
		||||
        // @todo: Quit app with back button. How to tell if we're at root level?
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
 | 
			
		||||
@ -25,9 +25,9 @@ import {
 | 
			
		||||
    ElementRef,
 | 
			
		||||
} from '@angular/core';
 | 
			
		||||
import { IonSlides } from '@ionic/angular';
 | 
			
		||||
import { BackButtonEvent } from '@ionic/core';
 | 
			
		||||
import { Subscription } from 'rxjs';
 | 
			
		||||
 | 
			
		||||
import { CoreApp } from '@services/app';
 | 
			
		||||
import { Platform, Translate } from '@singletons';
 | 
			
		||||
import { CoreSettingsHelper } from '@features/settings/services/settings-helper';
 | 
			
		||||
 | 
			
		||||
@ -81,7 +81,7 @@ export class CoreTabsBaseComponent<T extends CoreTabBase> implements OnInit, Aft
 | 
			
		||||
    protected selectHistory: string[] = [];
 | 
			
		||||
 | 
			
		||||
    protected firstSelectedTab?: string; // ID of the first selected tab to control history.
 | 
			
		||||
    protected unregisterBackButtonAction: any;
 | 
			
		||||
    protected backButtonFunction: (event: BackButtonEvent) => void;
 | 
			
		||||
    protected languageChangedSubscription?: Subscription;
 | 
			
		||||
    protected isInTransition = false; // Weather Slides is in transition.
 | 
			
		||||
    protected slidesSwiper: any; // eslint-disable-line @typescript-eslint/no-explicit-any
 | 
			
		||||
@ -91,6 +91,7 @@ export class CoreTabsBaseComponent<T extends CoreTabBase> implements OnInit, Aft
 | 
			
		||||
    constructor(
 | 
			
		||||
        protected element: ElementRef,
 | 
			
		||||
    ) {
 | 
			
		||||
        this.backButtonFunction = this.backButtonClicked.bind(this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@ -171,43 +172,47 @@ export class CoreTabsBaseComponent<T extends CoreTabBase> implements OnInit, Aft
 | 
			
		||||
 | 
			
		||||
        this.calculateSlides();
 | 
			
		||||
 | 
			
		||||
        this.registerBackButtonAction();
 | 
			
		||||
        document.addEventListener('ionBackButton', this.backButtonFunction);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Register back button action.
 | 
			
		||||
     * Back button clicked.
 | 
			
		||||
     *
 | 
			
		||||
     * @param event Event.
 | 
			
		||||
     */
 | 
			
		||||
    protected registerBackButtonAction(): void {
 | 
			
		||||
        this.unregisterBackButtonAction = CoreApp.registerBackButtonAction(() => {
 | 
			
		||||
            // The previous page in history is not the last one, we need the previous one.
 | 
			
		||||
    protected backButtonClicked(event: BackButtonEvent): void {
 | 
			
		||||
        event.detail.register(40, (processNextHandler: () => void) => {
 | 
			
		||||
            if (this.selectHistory.length > 1) {
 | 
			
		||||
                const tabIndex = this.selectHistory[this.selectHistory.length - 2];
 | 
			
		||||
                // The previous page in history is not the last one, we need the previous one.
 | 
			
		||||
                const previousTabId = this.selectHistory[this.selectHistory.length - 2];
 | 
			
		||||
 | 
			
		||||
                // Remove curent and previous tabs from history.
 | 
			
		||||
                this.selectHistory = this.selectHistory.filter((tabId) => this.selected != tabId && tabIndex != tabId);
 | 
			
		||||
                this.selectHistory = this.selectHistory.filter((tabId) => this.selected != tabId && previousTabId != tabId);
 | 
			
		||||
 | 
			
		||||
                this.selectTab(tabIndex);
 | 
			
		||||
                this.selectTab(previousTabId);
 | 
			
		||||
 | 
			
		||||
                return true;
 | 
			
		||||
            } else if (this.selected != this.firstSelectedTab) {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (this.firstSelectedTab && this.selected != this.firstSelectedTab) {
 | 
			
		||||
                // All history is gone but we are not in the first selected tab.
 | 
			
		||||
                this.selectHistory = [];
 | 
			
		||||
 | 
			
		||||
                this.selectTab(this.firstSelectedTab!);
 | 
			
		||||
                this.selectTab(this.firstSelectedTab);
 | 
			
		||||
 | 
			
		||||
                return true;
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return false;
 | 
			
		||||
        }, 750);
 | 
			
		||||
            processNextHandler();
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * User left the page that contains the component.
 | 
			
		||||
     */
 | 
			
		||||
    ionViewDidLeave(): void {
 | 
			
		||||
        // Unregister the custom back button action for this page
 | 
			
		||||
        this.unregisterBackButtonAction && this.unregisterBackButtonAction();
 | 
			
		||||
        // Unregister the custom back button action for this component.
 | 
			
		||||
        document.removeEventListener('ionBackButton', this.backButtonFunction);
 | 
			
		||||
 | 
			
		||||
        this.isCurrentView = false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -1,4 +1,5 @@
 | 
			
		||||
<ion-tabs #mainTabs [hidden]="!showTabs" [class]="'placement-' + tabsPlacement" [class.tabshidden]="hidden">
 | 
			
		||||
<ion-tabs #mainTabs [hidden]="!showTabs" [class]="'placement-' + tabsPlacement" [class.tabshidden]="hidden"
 | 
			
		||||
    (ionTabsDidChange)="tabChanged($event)">
 | 
			
		||||
    <ion-tab-bar slot="bottom" [hidden]="hidden">
 | 
			
		||||
        <ion-spinner *ngIf="!loaded"></ion-spinner>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -15,6 +15,7 @@
 | 
			
		||||
import { Component, OnInit, OnDestroy, ViewChild, ChangeDetectorRef } from '@angular/core';
 | 
			
		||||
import { ActivatedRoute, Router } from '@angular/router';
 | 
			
		||||
import { IonTabs } from '@ionic/angular';
 | 
			
		||||
import { BackButtonEvent } from '@ionic/core';
 | 
			
		||||
import { Subscription } from 'rxjs';
 | 
			
		||||
 | 
			
		||||
import { CoreApp } from '@services/app';
 | 
			
		||||
@ -50,6 +51,11 @@ export class CoreMainMenuPage implements OnInit, OnDestroy {
 | 
			
		||||
    protected pendingRedirect?: CoreRedirectPayload;
 | 
			
		||||
    protected urlToOpen?: string;
 | 
			
		||||
    protected keyboardObserver?: CoreEventObserver;
 | 
			
		||||
    protected resizeFunction: () => void;
 | 
			
		||||
    protected backButtonFunction: (event: BackButtonEvent) => void;
 | 
			
		||||
    protected selectHistory: string[] = [];
 | 
			
		||||
    protected selectedTab?: string;
 | 
			
		||||
    protected firstSelectedTab?: string;
 | 
			
		||||
 | 
			
		||||
    @ViewChild('mainTabs') mainTabs?: IonTabs;
 | 
			
		||||
 | 
			
		||||
@ -57,7 +63,10 @@ export class CoreMainMenuPage implements OnInit, OnDestroy {
 | 
			
		||||
        protected route: ActivatedRoute,
 | 
			
		||||
        protected changeDetector: ChangeDetectorRef,
 | 
			
		||||
        protected router: Router,
 | 
			
		||||
    ) {}
 | 
			
		||||
    ) {
 | 
			
		||||
        this.resizeFunction = this.initHandlers.bind(this);
 | 
			
		||||
        this.backButtonFunction = this.backButtonClicked.bind(this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Initialize the component.
 | 
			
		||||
@ -100,7 +109,8 @@ export class CoreMainMenuPage implements OnInit, OnDestroy {
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        window.addEventListener('resize', this.initHandlers.bind(this));
 | 
			
		||||
        window.addEventListener('resize', this.resizeFunction);
 | 
			
		||||
        document.addEventListener('ionBackButton', this.backButtonFunction);
 | 
			
		||||
 | 
			
		||||
        if (CoreApp.isIOS()) {
 | 
			
		||||
            // In iOS, the resize event is triggered before the keyboard is opened/closed and not triggered again once done.
 | 
			
		||||
@ -209,7 +219,8 @@ export class CoreMainMenuPage implements OnInit, OnDestroy {
 | 
			
		||||
    ngOnDestroy(): void {
 | 
			
		||||
        this.subscription?.unsubscribe();
 | 
			
		||||
        this.redirectObs?.off();
 | 
			
		||||
        window.removeEventListener('resize', this.initHandlers.bind(this));
 | 
			
		||||
        window.removeEventListener('resize', this.resizeFunction);
 | 
			
		||||
        document.removeEventListener('ionBackButton', this.backButtonFunction);
 | 
			
		||||
        this.keyboardObserver?.off();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -262,4 +273,46 @@ export class CoreMainMenuPage implements OnInit, OnDestroy {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Selected tab has changed.
 | 
			
		||||
     *
 | 
			
		||||
     * @param event Event.
 | 
			
		||||
     */
 | 
			
		||||
    tabChanged(event: {tab: string}): void {
 | 
			
		||||
        this.selectedTab = event.tab;
 | 
			
		||||
        this.firstSelectedTab = this.firstSelectedTab ?? event.tab;
 | 
			
		||||
        this.selectHistory.push(event.tab);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Back button clicked.
 | 
			
		||||
     *
 | 
			
		||||
     * @param event Event.
 | 
			
		||||
     */
 | 
			
		||||
    protected backButtonClicked(event: BackButtonEvent): void {
 | 
			
		||||
        event.detail.register(20, (processNextHandler: () => void) => {
 | 
			
		||||
            if (this.selectHistory.length > 1) {
 | 
			
		||||
                // The previous page in history is not the last one, we need the previous one.
 | 
			
		||||
                const previousTab = this.selectHistory[this.selectHistory.length - 2];
 | 
			
		||||
 | 
			
		||||
                // Remove curent and previous tabs from history.
 | 
			
		||||
                this.selectHistory = this.selectHistory.filter((tab) => this.selectedTab != tab && previousTab != tab);
 | 
			
		||||
 | 
			
		||||
                this.mainTabs?.select(previousTab);
 | 
			
		||||
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (this.firstSelectedTab && this.selectedTab != this.firstSelectedTab) {
 | 
			
		||||
                // All history is gone but we are not in the first selected tab.
 | 
			
		||||
                this.selectHistory = [];
 | 
			
		||||
                this.mainTabs?.select(this.firstSelectedTab);
 | 
			
		||||
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            processNextHandler();
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -56,7 +56,6 @@ export class CoreAppProvider {
 | 
			
		||||
    protected isKeyboardShown = false;
 | 
			
		||||
    protected keyboardOpening = false;
 | 
			
		||||
    protected keyboardClosing = false;
 | 
			
		||||
    protected backActions: {callback: () => boolean; priority: number}[] = [];
 | 
			
		||||
    protected forceOffline = false;
 | 
			
		||||
    protected redirect?: CoreRedirectData;
 | 
			
		||||
 | 
			
		||||
@ -68,11 +67,6 @@ export class CoreAppProvider {
 | 
			
		||||
        this.schemaVersionsManager = new Promise(resolve => this.resolveSchemaVersionsManager = resolve);
 | 
			
		||||
        this.db = CoreDB.getDB(DBNAME);
 | 
			
		||||
        this.logger = CoreLogger.getInstance('CoreAppProvider');
 | 
			
		||||
 | 
			
		||||
        // @todo
 | 
			
		||||
        // this.platform.registerBackButtonAction(() => {
 | 
			
		||||
        //     this.backButtonAction();
 | 
			
		||||
        // }, 100);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@ -592,37 +586,18 @@ export class CoreAppProvider {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The back button event is triggered when the user presses the native
 | 
			
		||||
     * platform's back button, also referred to as the "hardware" back button.
 | 
			
		||||
     * This event is only used within Cordova apps running on Android and
 | 
			
		||||
     * Windows platforms. This event is not fired on iOS since iOS doesn't come
 | 
			
		||||
     * with a hardware back button in the same sense an Android or Windows device
 | 
			
		||||
     * does.
 | 
			
		||||
     * Register a back button action.
 | 
			
		||||
     * This function is deprecated and no longer works. You should now use Ionic events directly, please see:
 | 
			
		||||
     * https://ionicframework.com/docs/developing/hardware-back-button
 | 
			
		||||
     *
 | 
			
		||||
     * Registering a hardware back button action and setting a priority allows
 | 
			
		||||
     * apps to control which action should be called when the hardware back
 | 
			
		||||
     * button is pressed. This method decides which of the registered back button
 | 
			
		||||
     * actions has the highest priority and should be called.
 | 
			
		||||
     *
 | 
			
		||||
     * @param callback Called when the back button is pressed, if this registered action has the highest priority.
 | 
			
		||||
     * @param priority Set the priority for this action. All actions sorted by priority will be executed since one of
 | 
			
		||||
     *                 them returns true.
 | 
			
		||||
     *                 - Priorities higher or equal than 1000 will go before closing modals
 | 
			
		||||
     *                 - Priorities lower than 500 will only be executed if you are in the first state of the app (before exit).
 | 
			
		||||
     * @param callback Called when the back button is pressed.
 | 
			
		||||
     * @param priority Priority.
 | 
			
		||||
     * @return A function that, when called, will unregister the back button action.
 | 
			
		||||
     * @deprecated since 3.9.5
 | 
			
		||||
     */
 | 
			
		||||
    registerBackButtonAction(callback: () => boolean, priority: number = 0): () => boolean {
 | 
			
		||||
        const action = { callback, priority };
 | 
			
		||||
 | 
			
		||||
        this.backActions.push(action);
 | 
			
		||||
 | 
			
		||||
        this.backActions.sort((a, b) => b.priority - a.priority);
 | 
			
		||||
 | 
			
		||||
        return (): boolean => {
 | 
			
		||||
            const index = this.backActions.indexOf(action);
 | 
			
		||||
 | 
			
		||||
            return index >= 0 && !!this.backActions.splice(index, 1);
 | 
			
		||||
        };
 | 
			
		||||
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
 | 
			
		||||
    registerBackButtonAction(callback: () => boolean, priority = 0): () => boolean {
 | 
			
		||||
        return () => false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user