From d4b7de321cdfc42cfb62038001c8d551568a6ce2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pau=20Ferrer=20Oca=C3=B1a?= Date: Thu, 21 Oct 2021 13:20:00 +0200 Subject: [PATCH] MOBILE-3899 mainmenu: Hide main menu on navigation level > 1 --- scripts/langindex.json | 2 - .../mod/h5pactivity/components/index/index.ts | 45 ------- src/core/classes/tabs.ts | 18 +-- .../features/mainmenu/pages/menu/menu.html | 36 ++---- .../features/mainmenu/pages/menu/menu.scss | 20 ++- src/core/features/mainmenu/pages/menu/menu.ts | 122 ++++++------------ src/core/lang.json | 2 - 7 files changed, 75 insertions(+), 170 deletions(-) diff --git a/scripts/langindex.json b/scripts/langindex.json index 9cd4ae19c..15dc8e894 100644 --- a/scripts/langindex.json +++ b/scripts/langindex.json @@ -1439,8 +1439,6 @@ "core.completion-alt-manual-y-override": "completion", "core.confirmcanceledit": "local_moodlemobileapp", "core.confirmdeletefile": "repository", - "core.confirmgotabroot": "local_moodlemobileapp", - "core.confirmgotabrootdefault": "local_moodlemobileapp", "core.confirmleaveunknownchanges": "local_moodlemobileapp", "core.confirmloss": "local_moodlemobileapp", "core.confirmopeninbrowser": "local_moodlemobileapp", diff --git a/src/addons/mod/h5pactivity/components/index/index.ts b/src/addons/mod/h5pactivity/components/index/index.ts index d7bd10f69..cf7b0b60b 100644 --- a/src/addons/mod/h5pactivity/components/index/index.ts +++ b/src/addons/mod/h5pactivity/components/index/index.ts @@ -46,7 +46,6 @@ import { import { CoreFileHelper } from '@services/file-helper'; import { AddonModH5PActivityModuleHandlerService } from '../../services/handlers/module'; import { CoreMainMenuPage } from '@features/mainmenu/pages/menu/menu'; -import { Platform } from '@singletons'; /** * Component that displays an H5P activity entry page. @@ -81,13 +80,11 @@ export class AddonModH5PActivityIndexComponent extends CoreCourseModuleMainActiv isOpeningPage = false; canViewAllAttempts = false; - protected listeningResize = false; protected fetchContentDefaultError = 'addon.mod_h5pactivity.errorgetactivity'; protected syncEventName = AddonModH5PActivitySyncProvider.AUTO_SYNCED; protected site: CoreSite; protected observer?: CoreEventObserver; protected messageListenerFunction: (event: MessageEvent) => Promise; - protected resizeFunction: () => void; constructor( protected mainMenuPage: CoreMainMenuPage, @@ -102,7 +99,6 @@ export class AddonModH5PActivityIndexComponent extends CoreCourseModuleMainActiv // Listen for messages from the iframe. this.messageListenerFunction = this.onIframeMessage.bind(this); window.addEventListener('message', this.messageListenerFunction); - this.resizeFunction = this.contentResized.bind(this); } /** @@ -375,8 +371,6 @@ export class AddonModH5PActivityIndexComponent extends CoreCourseModuleMainActiv AddonModH5PActivity.logView(this.h5pActivity!.id, this.h5pActivity!.name, this.siteId); CoreCourse.checkModuleCompletion(this.courseId, this.module.completiondata); - - this.setResizeListener(); } /** @@ -506,45 +500,6 @@ export class AddonModH5PActivityIndexComponent extends CoreCourseModuleMainActiv } } - /** - * Set the resize listener if needed. - */ - setResizeListener(): void { - if (!this.playing || this.listeningResize) { - return; - } - - this.listeningResize = true; - window.addEventListener('resize', this.contentResized.bind(this)); - this.contentResized(); - } - - /** - * On content resize, change visibility of the main menu: show on portrait and hide on landscape. - */ - contentResized(): void { - this.mainMenuPage.changeVisibility(Platform.isPortrait()); - } - - /** - * @inheritdoc - */ - ionViewDidEnter(): void { - this.setResizeListener(); - } - - /** - * @inheritdoc - */ - ionViewWillLeave(): void { - this.mainMenuPage.changeVisibility(true); - - if (this.listeningResize) { - this.listeningResize = false; - window.removeEventListener('resize', this.resizeFunction); - } - } - /** * Component destroyed. */ diff --git a/src/core/classes/tabs.ts b/src/core/classes/tabs.ts index 575f4c653..d77ca5b4d 100644 --- a/src/core/classes/tabs.ts +++ b/src/core/classes/tabs.ts @@ -74,7 +74,7 @@ export class CoreTabsBaseComponent implements OnInit, Aft protected tabsElement?: HTMLElement; // The tabs parent element. It's the element that will be "scrolled" to hide tabs. protected tabBarElement?: HTMLIonTabBarElement; // The top tab bar element. protected tabsShown = true; - protected resizeFunction?: EventListenerOrEventListenerObject; + protected resizeFunction: EventListenerOrEventListenerObject; protected isDestroyed = false; protected isCurrentView = true; protected shouldSlideToInitial = false; // Whether we need to slide to the initial slide because it's out of view. @@ -97,6 +97,8 @@ export class CoreTabsBaseComponent implements OnInit, Aft protected element: ElementRef, ) { this.backButtonFunction = this.backButtonClicked.bind(this); + this.resizeFunction = this.windowResized.bind(this); + this.tabAction = new CoreTabsRoleTab(this); } @@ -130,9 +132,7 @@ export class CoreTabsBaseComponent implements OnInit, Aft await this.initializeTabs(); } - this.resizeFunction = this.windowResized.bind(this); - - window.addEventListener('resize', this.resizeFunction!); + window.addEventListener('resize', this.resizeFunction); } /** @@ -162,17 +162,17 @@ export class CoreTabsBaseComponent implements OnInit, Aft if (showTabs) { // Smooth translation. - this.tabBarElement!.classList.remove('tabs-hidden'); + this.tabBarElement.classList.remove('tabs-hidden'); if (scroll === 0) { - this.tabBarElement!.style.height = ''; + this.tabBarElement.style.height = ''; this.previousLastScroll = this.lastScroll; this.lastScroll = 0; } else if (scroll !== undefined) { - this.tabBarElement!.style.height = (this.tabBarHeight - scroll) + 'px'; + this.tabBarElement.style.height = (this.tabBarHeight - scroll) + 'px'; } } else { - this.tabBarElement!.classList.add('tabs-hidden'); - this.tabBarElement!.style.height = ''; + this.tabBarElement.classList.add('tabs-hidden'); + this.tabBarElement.style.height = ''; } this.tabsShown = showTabs; diff --git a/src/core/features/mainmenu/pages/menu/menu.html b/src/core/features/mainmenu/pages/menu/menu.html index 655919ab4..b888971dc 100644 --- a/src/core/features/mainmenu/pages/menu/menu.html +++ b/src/core/features/mainmenu/pages/menu/menu.html @@ -1,22 +1,12 @@ - - + + - + @@ -26,16 +16,8 @@ - + {{ 'core.more' | translate }} diff --git a/src/core/features/mainmenu/pages/menu/menu.scss b/src/core/features/mainmenu/pages/menu/menu.scss index 53f005f0d..7f362ec1d 100644 --- a/src/core/features/mainmenu/pages/menu/menu.scss +++ b/src/core/features/mainmenu/pages/menu/menu.scss @@ -9,9 +9,20 @@ } @if ($core-always-show-main-menu) { - ion-tab-bar[hidden] { - display: flex !important; + ion-tabs.placement-bottom ion-tab-bar { + height: var(--menutabbar-size) !important; + visibility: visible !important; + transform: translateY(0) !important; } + } @else { + ion-tabs.tabshidden.placement-bottom ion-tab-bar { + pointer-events: none; + + ion-tab-button { + height: auto; + } + } + } ion-tab-button ion-icon { @@ -56,12 +67,15 @@ @include border-end(var(--border)); box-shadow: 3px 0 3px rgba(var(--drop-shadow)); border-top: 0; + justify-content: flex-start; @include padding(var(--ion-safe-area-top), 0px, var(--ion-safe-area-bottom), var(--ion-safe-area-left)); ion-tab-button { width: 100%; - height: auto; + min-height: var(--menutabbar-size); + flex: 0; + ion-badge { top: calc(50% - 20px); } diff --git a/src/core/features/mainmenu/pages/menu/menu.ts b/src/core/features/mainmenu/pages/menu/menu.ts index 1eb2af34f..36d929f4d 100644 --- a/src/core/features/mainmenu/pages/menu/menu.ts +++ b/src/core/features/mainmenu/pages/menu/menu.ts @@ -12,8 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { Component, OnInit, OnDestroy, ViewChild, ChangeDetectorRef } from '@angular/core'; -import { ActivatedRoute } from '@angular/router'; +import { Component, OnInit, OnDestroy, ViewChild } from '@angular/core'; import { IonTabs } from '@ionic/angular'; import { BackButtonEvent } from '@ionic/core'; import { Subscription } from 'rxjs'; @@ -22,11 +21,13 @@ import { CoreApp } from '@services/app'; 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 { Router } from '@singletons'; import { CoreUtils } from '@services/utils/utils'; import { CoreAriaRoleTab, CoreAriaRoleTabFindable } from '@classes/aria-role-tab'; import { CoreNavigator } from '@services/navigator'; +import { filter } from 'rxjs/operators'; +import { NavigationEnd } from '@angular/router'; +import { trigger, state, style, transition, animate } from '@angular/animations'; /** * Page that displays the main menu of the app. @@ -34,6 +35,25 @@ import { CoreNavigator } from '@services/navigator'; @Component({ selector: 'page-core-mainmenu', templateUrl: 'menu.html', + animations: [ + trigger('menuShowHideAnimation', [ + state('hidden', style({ + height: 0, + visibility: 'hidden', + transform: 'translateY(100%)', + })), + state('visible', style({ + visibility: 'visible', + })), + transition('visible => hidden', [ + style({ transform: 'translateY(0)' }), + animate('500ms ease-in-out', style({ transform: 'translateY(100%)' })), + ]), + transition('hidden => visible', [ + style({ transform: 'translateY(100%)', visibility: 'visible', height: '*' }), + animate('500ms ease-in-out', style({ transform: 'translateY(0)' })), + ]), + ])], styleUrls: ['menu.scss'], }) export class CoreMainMenuPage implements OnInit, OnDestroy { @@ -43,11 +63,12 @@ export class CoreMainMenuPage implements OnInit, OnDestroy { loaded = false; showTabs = false; tabsPlacement: 'bottom' | 'side' = 'bottom'; - hidden = false; morePageName = CoreMainMenuProvider.MORE_PAGE_NAME; selectedTab?: string; + isMainScreen = false; protected subscription?: Subscription; + protected navSubscription?: Subscription; protected keyboardObserver?: CoreEventObserver; protected resizeFunction: () => void; protected backButtonFunction: (event: BackButtonEvent) => void; @@ -58,21 +79,27 @@ export class CoreMainMenuPage implements OnInit, OnDestroy { tabAction: CoreMainMenuRoleTab; - constructor( - protected route: ActivatedRoute, - protected changeDetector: ChangeDetectorRef, - ) { + constructor() { this.resizeFunction = this.initHandlers.bind(this); this.backButtonFunction = this.backButtonClicked.bind(this); this.tabAction = new CoreMainMenuRoleTab(this); + + // Listen navigation events to show or hide tabs. + this.navSubscription = Router.events + .pipe(filter(event => event instanceof NavigationEnd)) + .subscribe(async () => { + this.isMainScreen = !this.mainTabs?.outlet.canGoBack(); + }); } /** - * Initialize the component. + * @inheritdoc */ - ngOnInit(): void { + async ngOnInit(): Promise { this.showTabs = true; + this.isMainScreen = !this.mainTabs?.outlet.canGoBack(); + this.subscription = CoreMainMenuDelegate.getHandlersObservable().subscribe((handlers) => { // Remove the handlers that should only appear in the More menu. this.allHandlers = handlers.filter((handler) => !handler.onlyInMore); @@ -134,78 +161,16 @@ export class CoreMainMenuPage implements OnInit, OnDestroy { } /** - * Change tabs visibility to show/hide them from the view. - * - * @param visible If show or hide the tabs. - */ - changeVisibility(visible: boolean): void { - if (this.hidden == visible) { - // Change needed. - this.hidden = !visible; - - /* setTimeout(() => { - this.viewCtrl.getContent().resize(); - });*/ - } - } - - /** - * Page destroyed. + * @inheritdoc */ ngOnDestroy(): void { this.subscription?.unsubscribe(); + this.navSubscription?.unsubscribe(); window.removeEventListener('resize', this.resizeFunction); document.removeEventListener('ionBackButton', this.backButtonFunction); this.keyboardObserver?.off(); } - /** - * Tab clicked. - * - * @param e Event. - * @param page Page of the tab. - */ - async tabClicked(e: Event, page: string): Promise { - if (this.mainTabs?.getSelected() != page) { - // Just change the tab. - return; - } - - e.preventDefault(); - e.stopPropagation(); - e.stopImmediatePropagation(); - - // Current tab was clicked. Check if user is already at root level. - const isMainMenuRoot = await this.currentRouteIsMainMenuRoot(); - if (isMainMenuRoot) { - return; // Already at root level, nothing to do. - } - - // Maybe the route isn't defined as it should. Check if the current path is the tab one. - const currentPath = CoreNavigator.getCurrentPath(); - if (currentPath == `/main/${page}`) { - return; // Already at root level, nothing to do. - } - - // Ask the user if he wants to go back to the root page of the tab. - try { - const tab = this.tabs.find((tab) => tab.page == page); - - if (tab?.title) { - await CoreDomUtils.showConfirm(Translate.instant('core.confirmgotabroot', { - name: Translate.instant(tab.title), - })); - } else { - await CoreDomUtils.showConfirm(Translate.instant('core.confirmgotabrootdefault')); - } - - // User confirmed, go to root. - this.mainTabs?.select(page); - } catch { - // User canceled. - } - } - /** * Selected tab has changed. * @@ -274,13 +239,6 @@ export class CoreMainMenuPage implements OnInit, OnDestroy { */ class CoreMainMenuRoleTab extends CoreAriaRoleTab { - /** - * @inheritdoc - */ - selectTab(tabId: string, e: Event): void { - this.componentInstance.tabClicked(e, tabId); - } - /** * @inheritdoc */ diff --git a/src/core/lang.json b/src/core/lang.json index 02beb3878..f067e4b9e 100644 --- a/src/core/lang.json +++ b/src/core/lang.json @@ -47,8 +47,6 @@ "completion-alt-manual-y-override": "Completed: {{$a.modname}} (set by {{$a.overrideuser}}). Select to mark as not complete.", "confirmcanceledit": "Are you sure you want to leave this page? All changes will be lost.", "confirmdeletefile": "Are you sure you want to delete this file?", - "confirmgotabroot": "Are you sure you want to go back to {{name}}?", - "confirmgotabrootdefault": "Are you sure you want to go to the initial page of the current tab?", "confirmleaveunknownchanges": "Are you sure you want to leave this page? If you have unsaved changes they will be lost.", "confirmloss": "Are you sure? All changes will be lost.", "confirmopeninbrowser": "Do you want to open it in a web browser?",