From 19e0cf59e54c9f90149bfffc09255ac1099665c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pau=20Ferrer=20Oca=C3=B1a?= Date: Wed, 6 Mar 2019 14:54:40 +0100 Subject: [PATCH] MOBILE-2903 menu: Show menu items depending on device width --- src/components/ion-tabs/ion-tabs.ts | 4 +++ src/core/mainmenu/pages/menu/menu.ts | 43 +++++++++++++++++-------- src/core/mainmenu/pages/more/more.ts | 39 ++++++++++++++-------- src/core/mainmenu/providers/mainmenu.ts | 19 +++++++++++ 4 files changed, 78 insertions(+), 27 deletions(-) diff --git a/src/components/ion-tabs/ion-tabs.ts b/src/components/ion-tabs/ion-tabs.ts index deeb76a53..76fff38fe 100644 --- a/src/components/ion-tabs/ion-tabs.ts +++ b/src/components/ion-tabs/ion-tabs.ts @@ -223,6 +223,10 @@ export class CoreIonTabsComponent extends Tabs implements OnDestroy { * @param {CoreIonTabComponent} tab The tab to remove. */ remove(tab: CoreIonTabComponent): void { + if (tab.isSelected) { + // TODO: If selected we should move this navigation to the phantom tab. + } + // First search in the list of initialized tabs. let index = this._tabs.indexOf(tab); diff --git a/src/core/mainmenu/pages/menu/menu.ts b/src/core/mainmenu/pages/menu/menu.ts index ae3f68830..05d1afcff 100644 --- a/src/core/mainmenu/pages/menu/menu.ts +++ b/src/core/mainmenu/pages/menu/menu.ts @@ -30,6 +30,7 @@ import { CoreMainMenuDelegate, CoreMainMenuHandlerToDisplay } from '../../provid }) export class CoreMainMenuPage implements OnDestroy { tabs: CoreMainMenuHandlerToDisplay[] = []; + allHandlers: CoreMainMenuHandlerToDisplay[]; loaded = false; redirectPage: string; redirectParams: any; @@ -42,7 +43,8 @@ export class CoreMainMenuPage implements OnDestroy { @ViewChild('mainTabs') mainTabs: CoreIonTabsComponent; constructor(private menuDelegate: CoreMainMenuDelegate, private sitesProvider: CoreSitesProvider, navParams: NavParams, - private navCtrl: NavController, private eventsProvider: CoreEventsProvider, private cdr: ChangeDetectorRef) { + private navCtrl: NavController, private eventsProvider: CoreEventsProvider, private cdr: ChangeDetectorRef, + private mainMenuProvider: CoreMainMenuProvider) { // Check if the menu was loaded with a redirect. const redirectPage = navParams.get('redirectPage'); @@ -78,10 +80,32 @@ export class CoreMainMenuPage implements OnDestroy { this.subscription = this.menuDelegate.getHandlers().subscribe((handlers) => { // Remove the handlers that should only appear in the More menu. - handlers = handlers.filter((handler) => { + this.allHandlers = handlers.filter((handler) => { return !handler.onlyInMore; }); - handlers = handlers.slice(0, CoreMainMenuProvider.NUM_MAIN_HANDLERS); // Get main handlers. + + 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.initHandlers.bind(this)); + } + + /** + * Init handlers on change (size or handlers). + */ + initHandlers(): void { + if (this.allHandlers) { + const handlers = this.allHandlers.slice(0, this.mainMenuProvider.getNumItems()); // Get main handlers. // Re-build the list of tabs. If a handler is already in the list, use existing object to prevent re-creating the tab. const newTabs = []; @@ -105,17 +129,7 @@ export class CoreMainMenuPage implements OnDestroy { }); this.loaded = this.menuDelegate.areHandlersLoaded(); - - 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; - } - }); - } - }); + } } /** @@ -153,5 +167,6 @@ export class CoreMainMenuPage implements OnDestroy { ngOnDestroy(): void { this.subscription && this.subscription.unsubscribe(); this.redirectObs && this.redirectObs.off(); + window.removeEventListener('resize', this.initHandlers.bind(this)); } } diff --git a/src/core/mainmenu/pages/more/more.ts b/src/core/mainmenu/pages/more/more.ts index 9027f7012..03fc83452 100644 --- a/src/core/mainmenu/pages/more/more.ts +++ b/src/core/mainmenu/pages/more/more.ts @@ -29,6 +29,7 @@ import { CoreMainMenuProvider, CoreMainMenuCustomItem } from '../../providers/ma }) export class CoreMainMenuMorePage implements OnDestroy { handlers: CoreMainMenuHandlerData[]; + allHandlers: CoreMainMenuHandlerData[]; handlersLoaded: boolean; siteInfo: any; siteName: string; @@ -58,32 +59,44 @@ export class CoreMainMenuMorePage implements OnDestroy { ionViewDidLoad(): void { // Load the handlers. this.subscription = this.menuDelegate.getHandlers().subscribe((handlers) => { - // Calculate the main handlers to not display them in this view. - const mainHandlers = handlers.filter((handler) => { - return !handler.onlyInMore; - }).slice(0, CoreMainMenuProvider.NUM_MAIN_HANDLERS); + this.allHandlers = handlers; - // Get only the handlers that don't appear in the main view. - this.handlers = []; - handlers.forEach((handler) => { - if (mainHandlers.indexOf(handler) == -1) { - this.handlers.push(handler); - } - }); - - this.handlersLoaded = this.menuDelegate.areHandlersLoaded(); + this.initHandlers(); }); + + window.addEventListener('resize', this.initHandlers.bind(this)); } /** * Page destroyed. */ ngOnDestroy(): void { + window.removeEventListener('resize', this.initHandlers.bind(this)); + if (this.subscription) { this.subscription.unsubscribe(); } } + /** + * Init handlers on change (size or handlers). + */ + initHandlers(): void { + if (this.allHandlers) { + // Calculate the main handlers not to display them in this view. + const mainHandlers = this.allHandlers.filter((handler) => { + return !handler.onlyInMore; + }).slice(0, this.mainMenuProvider.getNumItems()); + + // Get only the handlers that don't appear in the main view. + this.handlers = this.allHandlers.filter((handler) => { + return mainHandlers.indexOf(handler) == -1; + }); + + this.handlersLoaded = this.menuDelegate.areHandlersLoaded(); + } + } + /** * Load the site info required by the view. */ diff --git a/src/core/mainmenu/providers/mainmenu.ts b/src/core/mainmenu/providers/mainmenu.ts index ac38ef92b..e0fa54e02 100644 --- a/src/core/mainmenu/providers/mainmenu.ts +++ b/src/core/mainmenu/providers/mainmenu.ts @@ -52,6 +52,7 @@ export interface CoreMainMenuCustomItem { @Injectable() export class CoreMainMenuProvider { static NUM_MAIN_HANDLERS = 4; + static ITEM_MIN_WIDTH = 72; // Min with of every item, based on 5 items on a 360 pixel wide screen. constructor(private langProvider: CoreLangProvider, private sitesProvider: CoreSitesProvider) { } @@ -158,4 +159,22 @@ export class CoreMainMenuProvider { }); }); } + + /** + * Get the number of items to be shown on the main menu bar. + * + * @return {number} Number of items depending on the device width. + */ + getNumItems(): number { + if (window && window.innerWidth) { + let numElements; + + numElements = Math.floor(window.innerWidth / CoreMainMenuProvider.ITEM_MIN_WIDTH); + + // Set a mínimum elements to show and skip more button. + return numElements > 1 ? numElements - 1 : 1; + } + + return CoreMainMenuProvider.NUM_MAIN_HANDLERS; + } }