Skip to content

Commit

Permalink
fix(side-menu) production ready circumvent for #9
Browse files Browse the repository at this point in the history
  • Loading branch information
marckassay committed May 2, 2019
1 parent 925dffd commit 583bc00
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 46 deletions.
8 changes: 4 additions & 4 deletions src/app/app.component.html
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<ion-app ngClass="{{theme}}">
<ion-menu side="start" [swipeGesture]="areSideMenusInteractive">
<side-menu id="start" [cacheEnabled]="cacheSideMenus"></side-menu>
<ion-menu side="start" menuId="start" [swipeGesture]="areSideMenusInteractive">
<side-menu id="start"></side-menu>
</ion-menu>
<ion-menu side="end" [swipeGesture]="areSideMenusInteractive">
<side-menu id="end" [cacheEnabled]="cacheSideMenus"></side-menu>
<ion-menu side="end" menuId="end" [swipeGesture]="areSideMenusInteractive">
<side-menu id="end"></side-menu>
</ion-menu>
<ion-router-outlet main></ion-router-outlet>
</ion-app>
28 changes: 11 additions & 17 deletions src/app/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,12 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import { Component, ComponentFactoryResolver, Injector, OnInit, ViewChild } from '@angular/core';
import { Component, ComponentFactoryResolver, Injector, OnInit } from '@angular/core';
import { NavigationExtras, Router } from '@angular/router';
import { Platform } from '@ionic/angular';
import { BehaviorSubject } from 'rxjs';
import { environment as env } from 'src/environments/environment';

import { AppUtils } from './app.utils';
import { SideMenuComponent } from './components/side-menu/side-menu.component';
import { error, AppUtils } from './app.utils';
import { SideMenuService, SideMenuShapes, SideMenuStatusResponse } from './components/side-menu/side-menu.service';
import { HomePage } from './pages/home/home.page';
import { ScreenService } from './services/screen.service';
Expand All @@ -36,21 +34,12 @@ import { AppStorageData } from './services/storage/ait-storage.shapes';
templateUrl: 'app.component.html'
})
export class AppComponent implements OnInit {
@ViewChild('startMenu')
startMenu: SideMenuComponent;

@ViewChild('endMenu')
endMenu: SideMenuComponent;

/**
* The css app theme that `this.watchTheme()` provides updates
*/
theme: string;

/**
* Enables or disables sidemenus from being cached by `SideMenuComponent`.
*/
cacheSideMenus = env.enableViewCache;
private isStartUp: boolean;

/**
* To be used momentary to disable interaction
Expand All @@ -69,6 +58,7 @@ export class AppComponent implements OnInit {
private menuSvc: SideMenuService
) {
this.areSideMenusInteractive = false;
this.isStartUp = true;
}

ngOnInit(): void {
Expand All @@ -94,16 +84,20 @@ export class AppComponent implements OnInit {
injector: this.injector
});

// post app start-up; after start and end sidemenus have been loaded
} else if ((note.subject === 'start') &&
(note.response === true) &&
(this.areSideMenusInteractive === false)) {
(this.isStartUp === true)) {

this.isStartUp = false;
this.screenSvc.bootupScreen()
.then(() => {
this.screenSvc.fix();
this.areSideMenusInteractive = false;
})
.catch((reason) => {
error(reason);
});
} else if (note.subject === '*') {
this.areSideMenusInteractive = true;
}
}
}
Expand Down
25 changes: 15 additions & 10 deletions src/app/components/side-menu/side-menu.component.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Component, ComponentRef, Input, OnInit, ViewChild, ViewContainerRef } from '@angular/core';
import { environment as env } from 'src/environments/environment';

import { OnClosed, SideMenuEvent, SideMenuLoadRequest, SideMenuService, SideMenuShapes, SideMenuStatusRequest } from './side-menu.service';

Expand All @@ -12,26 +13,31 @@ export interface CacheViewRef {

@Component({
selector: 'side-menu',
template: '<ng-template #menu></ng-template>'
template: `<ng-template #menuContent></ng-template>`
})
export class SideMenuComponent implements OnInit {
@ViewChild('menu', { read: ViewContainerRef })
protected menu: ViewContainerRef;
@ViewChild('menuContent', { read: ViewContainerRef })
protected menuContent: ViewContainerRef;

@Input()
id: 'start' | 'end';

@Input()
swipeGestureEnabled: boolean;

/**
* When set to false, `cachedViewRefs` will only store 1 viewref which will be the latest viewref
* attached.
*/
cacheEnabled: boolean;
private cacheEnabled: boolean;


private cachedViewRefs: Array<CacheViewRef>;

constructor(protected menuSvc: SideMenuService) {
this.cachedViewRefs = [];
this.swipeGestureEnabled = false;
this.cacheEnabled = env.enableViewCache;
}

ngOnInit(): void {
Expand Down Expand Up @@ -119,20 +125,19 @@ export class SideMenuComponent implements OnInit {
private reattachComponent(uuid: string): void {
const component = this.getCache(uuid);
component.attached = true;
this.menu.detach();
this.menu.insert(component.componentRef.hostView);
this.menuContent.detach();
this.menuContent.insert(component.componentRef.hostView);
}

private attachComponent(note: SideMenuLoadRequest): void {
if (this.menu.length) {
this.menu.detach();
if (this.menuContent.length) {
this.menuContent.detach();
}

const component: ComponentRef<unknown> = this.menu.createComponent(note.component);
const component: ComponentRef<unknown> = this.menuContent.createComponent(note.component);
(component.instance as any).uuid = note.uuid;
(component.instance as any).injector = note.injector;
component.changeDetectorRef.detectChanges();

this.setCache(component);
}

Expand Down
60 changes: 51 additions & 9 deletions src/app/components/side-menu/side-menu.service.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Injectable, Injector } from '@angular/core';
import { MenuController } from '@ionic/angular';
import { NextObserver, Subject, Subscription } from 'rxjs';
import { error, log } from 'src/app/app.utils';

export interface OnClosed {
smOnClosed(): void;
Expand All @@ -20,8 +21,10 @@ export interface SideMenuStatusRequest {
uuid: string;
}


export interface SideMenuStatusResponse {
subject: 'start' | 'end';
// The '*' value is for this hack: https://github.com/ionic-team/ionic/issues/16002
subject: 'start' | 'end' | '*';
/**
* If `true`, the `subject` menu has been loaded. Otherwise `false`
*/
Expand Down Expand Up @@ -53,13 +56,15 @@ export class SideMenuService {
this.subject = new Subject<SideMenuShapes>();

// TODO: look into using `@HostListener` as an alternative to what is below:

this.menuCtrl.get('start').then((element: HTMLIonMenuElement) => {
element.addEventListener('ionDidClose', () => this.leftMenuClosed());
});

this.menuCtrl.get('end').then((element: HTMLIonMenuElement) => {
element.addEventListener('ionDidClose', () => this.rightMenuClosed());
});

}

send(value: SideMenuShapes): void {
Expand All @@ -81,23 +86,44 @@ export class SideMenuService {
async enableMenus(value: boolean): Promise<void> {
await this.enableLeftMenu(value);
await this.enableRightMenu(value);

return Promise.resolve();
}

enableLeftMenu(value: boolean): Promise<HTMLIonMenuElement> {
return this.menuCtrl.enable(value, 'start');
enableLeftMenu(value: boolean): Promise<void> {
return Promise.all([
this.menuCtrl.enable(value, 'start')])
.then(() => {
return Promise.resolve();
})
.catch((reason) => {
error(reason);
});
}

enableRightMenu(value: boolean): Promise<HTMLIonMenuElement> {
return this.menuCtrl.enable(value, 'end');
enableRightMenu(value: boolean): Promise<void> {
return Promise.all([
this.menuCtrl.enable(value, 'end')])
.then(() => {
return Promise.resolve();
})
.catch((reason) => {
error(reason);
});
}

openLeftMenu(): Promise<boolean> {
return this.menuCtrl.open('start');
return this.menuCtrl.open('start')
.then((value) => {
return Promise.resolve<boolean>(value);
});
}

openRightMenu(): Promise<boolean> {
return this.menuCtrl.open('end');
return this.menuCtrl.open('end')
.then((value) => {
return Promise.resolve<boolean>(value);
});
}

closeLeftMenu(): Promise<boolean> {
Expand All @@ -108,11 +134,27 @@ export class SideMenuService {
return this.menuCtrl.close('end');
}

leftMenuClosed(): void {
private leftMenuClosed(): void {
this.send({ subject: 'start', event: 'ionDidClose' });
}

rightMenuClosed(): void {
private rightMenuClosed(): void {
this.send({ subject: 'end', event: 'ionDidClose' });
}

// Hack for: https://github.com/ionic-team/ionic/issues/16002
swipeGestureEnabled(): void {
this.send({ subject: '*', response: true, uuid: '' });
}
// Broken: https://github.com/ionic-team/ionic/issues/16002
private swipeGesture(value: boolean, id: 'start' | 'end'): Promise<void> {
return this.menuCtrl.get(id)
.then((element) => {
element.swipeGesture = value;
return Promise.resolve();
})
.catch((reason) => {
error(reason);
});
}
}
19 changes: 13 additions & 6 deletions src/app/pages/display-page.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ export class DisplayPage implements OnInit, AfterViewInit {
* Runs when the page has finished leaving and is no longer the active page.
*/
ionViewDidLeave(): void {
this.isStartUp = false;
// this.isStartUp = false;
}

/**
Expand Down Expand Up @@ -175,8 +175,7 @@ export class DisplayPage implements OnInit, AfterViewInit {
* @param value true if timer is ticking
*/
protected async setAppToRunningMode(value: boolean): Promise<void> {
await this.menuSvc.enableLeftMenu(value === false);
await this.menuSvc.enableRightMenu(value === false);
await this.menuSvc.enableMenus(value === false);

if (this.timerState === SequenceStates.Completed) {
this.floatingbuttons.setToCompletedMode();
Expand Down Expand Up @@ -221,10 +220,11 @@ export class DisplayPage implements OnInit, AfterViewInit {
// enable side menus at the same time in an attempts to circumvent issue #16985 (https://github.com/ionic-team/ionic/issues/16985)
const resolveSideMenus = (resolve: () => void): void => {
this.floatingbuttons.setHomeButtonToVisible();
this.menuSvc.enableLeftMenu(true);

this.floatingbuttons.setProgramButtonToVisible();
this.menuSvc.enableRightMenu(true);

if (this.isStartUp === false) {
this.menuSvc.enableMenus(true);
}

this.progress.hide();

Expand Down Expand Up @@ -286,6 +286,13 @@ export class DisplayPage implements OnInit, AfterViewInit {
* `fabcontainer.component` (Child component). afterwards it will execute this function.
*/
async action(emission: FabEmission): Promise<void> {

if (this.isStartUp === true) {
this.isStartUp = false;
this.menuSvc.swipeGestureEnabled();
await this.menuSvc.enableMenus(true);
}

switch (emission.action) {
case FabAction.Home:
this.sots.sequencer.pause();
Expand Down

0 comments on commit 583bc00

Please sign in to comment.