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