commit
c93d6bccd3
|
@ -76,7 +76,7 @@
|
|||
{{ message.timecreated | coreFormatDate: "strftimedayshort" }}
|
||||
</h3>
|
||||
|
||||
<ion-chip class="addon-messages-unreadfrom" *ngIf="unreadMessageFrom && message.id == unreadMessageFrom" color="light">
|
||||
<ion-chip class="addon-messages-unreadfrom" *ngIf="unreadMessageFrom > 0 && message.id == unreadMessageFrom" color="light">
|
||||
<ion-label>{{ 'addon.messages.newmessages' | translate }}</ion-label>
|
||||
<ion-icon name="fas-arrow-down" aria-hidden="true"></ion-icon>
|
||||
</ion-chip>
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
<ion-tabs #mainTabs [hidden]="!showTabs" [class]="'placement-' + tabsPlacement"
|
||||
[class.tabshidden]="!isMainScreen && tabsPlacement == 'bottom'" (ionTabsDidChange)="tabChanged($event)">
|
||||
<ion-tab-bar slot="bottom" class="mainmenu-tabs"
|
||||
[@menuShowHideAnimation]="tabsPlacement == 'side' ? '' : (isMainScreen ? 'visible' : 'hidden')">
|
||||
<ion-tab-bar slot="bottom" class="mainmenu-tabs" [@menuVisibilityAnimation]="visibility">
|
||||
<ion-spinner *ngIf="!loaded" [attr.aria-label]="'core.loading' | translate"></ion-spinner>
|
||||
|
||||
<core-user-menu-button *ngIf="loaded && tabsPlacement == 'side'"></core-user-menu-button>
|
||||
|
|
|
@ -31,6 +31,8 @@ import { trigger, state, style, transition, animate } from '@angular/animations'
|
|||
import { CoreSites } from '@services/sites';
|
||||
import { CoreDom } from '@singletons/dom';
|
||||
|
||||
const ANIMATION_DURATION = 500;
|
||||
|
||||
/**
|
||||
* Page that displays the main menu of the app.
|
||||
*/
|
||||
|
@ -38,7 +40,7 @@ import { CoreDom } from '@singletons/dom';
|
|||
selector: 'page-core-mainmenu',
|
||||
templateUrl: 'menu.html',
|
||||
animations: [
|
||||
trigger('menuShowHideAnimation', [
|
||||
trigger('menuVisibilityAnimation', [
|
||||
state('hidden', style({
|
||||
height: 0,
|
||||
visibility: 'hidden',
|
||||
|
@ -49,11 +51,11 @@ import { CoreDom } from '@singletons/dom';
|
|||
})),
|
||||
transition('visible => hidden', [
|
||||
style({ transform: 'translateY(0)' }),
|
||||
animate('500ms ease-in-out', style({ transform: 'translateY(100%)' })),
|
||||
animate(`${ANIMATION_DURATION}ms 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)' })),
|
||||
animate(`${ANIMATION_DURATION}ms ease-in-out`, style({ transform: 'translateY(0)' })),
|
||||
]),
|
||||
])],
|
||||
styleUrls: ['menu.scss'],
|
||||
|
@ -69,6 +71,7 @@ export class CoreMainMenuPage implements OnInit, OnDestroy {
|
|||
selectedTab?: string;
|
||||
isMainScreen = false;
|
||||
moreBadge = false;
|
||||
visibility = 'hidden';
|
||||
|
||||
protected subscription?: Subscription;
|
||||
protected navSubscription?: Subscription;
|
||||
|
@ -93,8 +96,9 @@ export class CoreMainMenuPage implements OnInit, OnDestroy {
|
|||
// Listen navigation events to show or hide tabs.
|
||||
this.navSubscription = Router.events
|
||||
.pipe(filter(event => event instanceof NavigationEnd))
|
||||
.subscribe(async () => {
|
||||
.subscribe(() => {
|
||||
this.isMainScreen = !this.mainTabs?.outlet.canGoBack();
|
||||
this.updateVisibility();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -108,6 +112,7 @@ export class CoreMainMenuPage implements OnInit, OnDestroy {
|
|||
this.redirectOptions = CoreNavigator.getRouteParam('redirectOptions');
|
||||
|
||||
this.isMainScreen = !this.mainTabs?.outlet.canGoBack();
|
||||
this.updateVisibility();
|
||||
|
||||
this.subscription = CoreMainMenuDelegate.getHandlersObservable().subscribe((handlers) => {
|
||||
// Remove the handlers that should only appear in the More menu.
|
||||
|
@ -151,6 +156,7 @@ export class CoreMainMenuPage implements OnInit, OnDestroy {
|
|||
return;
|
||||
}
|
||||
this.tabsPlacement = CoreMainMenu.getTabPlacement();
|
||||
this.updateVisibility();
|
||||
|
||||
const handlers = this.allHandlers
|
||||
.filter((handler) => !handler.onlyInMore)
|
||||
|
@ -240,6 +246,20 @@ export class CoreMainMenuPage implements OnInit, OnDestroy {
|
|||
this.selectHistory.push(event.tab);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update menu visibility.
|
||||
*/
|
||||
protected updateVisibility(): void {
|
||||
const visibility = this.tabsPlacement == 'side' ? '' : (this.isMainScreen ? 'visible' : 'hidden');
|
||||
|
||||
if (visibility === this.visibility) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.visibility = visibility;
|
||||
this.notifyVisibilityUpdated();
|
||||
}
|
||||
|
||||
/**
|
||||
* Back button clicked.
|
||||
*
|
||||
|
@ -290,6 +310,17 @@ export class CoreMainMenuPage implements OnInit, OnDestroy {
|
|||
return !!CoreNavigator.getCurrentRoute({ routeData: { mainMenuTabRoot: CoreNavigator.getCurrentMainMenuTab() } });
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify that the menu visibility has been updated.
|
||||
*/
|
||||
protected async notifyVisibilityUpdated(): Promise<void> {
|
||||
await CoreUtils.nextTick();
|
||||
await CoreUtils.wait(ANIMATION_DURATION);
|
||||
await CoreUtils.nextTick();
|
||||
|
||||
CoreEvents.trigger(CoreMainMenuProvider.MAIN_MENU_VISIBILITY_UPDATED);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -33,6 +33,7 @@ declare module '@singletons/events' {
|
|||
*/
|
||||
export interface CoreEventsData {
|
||||
[CoreMainMenuProvider.MAIN_MENU_HANDLER_BADGE_UPDATED]: CoreMainMenuHandlerBadgeUpdatedEventData;
|
||||
[CoreMainMenuProvider.MAIN_MENU_VISIBILITY_UPDATED]: void;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -47,6 +48,7 @@ export class CoreMainMenuProvider {
|
|||
static readonly ITEM_MIN_WIDTH = 72; // Min with of every item, based on 5 items on a 360 pixel wide screen.
|
||||
static readonly MORE_PAGE_NAME = 'more';
|
||||
static readonly MAIN_MENU_HANDLER_BADGE_UPDATED = 'main_menu_handler_badge_updated';
|
||||
static readonly MAIN_MENU_VISIBILITY_UPDATED = 'main_menu_visbility_updated';
|
||||
|
||||
/**
|
||||
* Get the current main menu handlers.
|
||||
|
|
|
@ -32,7 +32,8 @@ import { CoreDomUtils } from '@services/utils/dom';
|
|||
import { AngularFrameworkDelegate } from '@singletons';
|
||||
import { CoreComponentsRegistry } from '@singletons/components-registry';
|
||||
import { CoreDom } from '@singletons/dom';
|
||||
import { CoreEventObserver } from '@singletons/events';
|
||||
import { CoreEventObserver, CoreEvents } from '@singletons/events';
|
||||
import { CoreMainMenuProvider } from '@features/mainmenu/services/mainmenu';
|
||||
|
||||
const ANIMATION_DURATION = 200;
|
||||
const USER_TOURS_BACK_BUTTON_PRIORITY = 100;
|
||||
|
@ -70,6 +71,7 @@ export class CoreUserToursUserTourComponent implements AfterViewInit, OnDestroy
|
|||
private wrapperTransform = '';
|
||||
private wrapperElement = new CorePromisedValue<HTMLElement>();
|
||||
private backButtonListener?: (event: BackButtonEvent) => void;
|
||||
protected mainMenuListener?: CoreEventObserver;
|
||||
protected resizeListener?: CoreEventObserver;
|
||||
protected scrollListener?: EventListener;
|
||||
protected content?: HTMLIonContentElement | null;
|
||||
|
@ -240,15 +242,10 @@ export class CoreUserToursUserTourComponent implements AfterViewInit, OnDestroy
|
|||
return;
|
||||
}
|
||||
|
||||
if (!this.resizeListener) {
|
||||
this.resizeListener = CoreDom.onWindowResize(() => {
|
||||
this.calculateStyles();
|
||||
});
|
||||
}
|
||||
|
||||
if (!this.content) {
|
||||
this.content = CoreDom.closest(this.focus, 'ion-content');
|
||||
}
|
||||
this.mainMenuListener = this.mainMenuListener ??
|
||||
CoreEvents.on(CoreMainMenuProvider.MAIN_MENU_VISIBILITY_UPDATED, () => this.calculateStyles());
|
||||
this.resizeListener = this.resizeListener ?? CoreDom.onWindowResize(() => this.calculateStyles());
|
||||
this.content = this.content ?? CoreDom.closest(this.focus, 'ion-content');
|
||||
|
||||
if (!this.scrollListener && this.content) {
|
||||
this.content.scrollEvents = true;
|
||||
|
@ -269,9 +266,11 @@ export class CoreUserToursUserTourComponent implements AfterViewInit, OnDestroy
|
|||
|
||||
this.active = false;
|
||||
|
||||
this.mainMenuListener?.off();
|
||||
this.resizeListener?.off();
|
||||
this.backButtonListener && document.removeEventListener('ionBackButton', this.backButtonListener);
|
||||
this.backButtonListener = undefined;
|
||||
this.mainMenuListener = undefined;
|
||||
this.resizeListener = undefined;
|
||||
|
||||
if (this.content && this.scrollListener) {
|
||||
|
|
Loading…
Reference in New Issue