Skip to content

Commit

Permalink
feat(settings): add runtime animations toggles
Browse files Browse the repository at this point in the history
  • Loading branch information
tomastrajan committed Jun 3, 2018
1 parent 9b86f52 commit 91131b4
Show file tree
Hide file tree
Showing 15 changed files with 285 additions and 73 deletions.
4 changes: 2 additions & 2 deletions e2e/protractor.conf.js
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
const { SpecReporter } = require('jasmine-spec-reporter');

exports.config = {
allScriptsTimeout: 11000,
allScriptsTimeout: 30000,
specs: [
'./src/**/*.e2e-spec.ts'
],
Expand All @@ -16,7 +16,7 @@ exports.config = {
framework: 'jasmine',
jasmineNodeOpts: {
showColors: true,
defaultTimeoutInterval: 30000,
defaultTimeoutInterval: 60000,
print: function () {
}
},
Expand Down
12 changes: 6 additions & 6 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,13 @@
"private": true,
"dependencies": {
"@angular/animations": "6.0.0",
"@angular/cdk": "^6.0.0",
"@angular/cdk": "^6.2.0",
"@angular/common": "^6.0.0",
"@angular/compiler": "^6.0.0",
"@angular/core": "^6.0.0",
"@angular/forms": "6.0.0",
"@angular/http": "6.0.0",
"@angular/material": "^6.0.0",
"@angular/material": "^6.2.0",
"@angular/platform-browser": "^6.0.0",
"@angular/platform-browser-dynamic": "6.0.0",
"@angular/router": "6.0.0",
Expand Down
47 changes: 36 additions & 11 deletions src/app/app.component.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import browser from 'browser-detect';
import { Title } from '@angular/platform-browser';
import { OverlayContainer } from '@angular/cdk/overlay';
import { Component, HostBinding, OnDestroy, OnInit } from '@angular/core';
Expand All @@ -9,12 +10,18 @@ import { takeUntil, filter } from 'rxjs/operators';
import {
ActionAuthLogin,
ActionAuthLogout,
AnimationsService,
selectorAuth,
routerTransition
} from '@app/core';
import { environment as env } from '@env/environment';

import { NIGHT_MODE_THEME, selectorSettings, SettingsState } from './settings';
import {
NIGHT_MODE_THEME,
selectorSettings,
SettingsState,
ActionSettingsChangeAnimationsPageDisabled
} from './settings';

@Component({
selector: 'anms-root',
Expand Down Expand Up @@ -47,9 +54,19 @@ export class AppComponent implements OnInit, OnDestroy {
public overlayContainer: OverlayContainer,
private store: Store<any>,
private router: Router,
private titleService: Title
private titleService: Title,
private animationService: AnimationsService
) {}

private static trackPageView(event: NavigationEnd) {
(<any>window).ga('set', 'page', event.urlAfterRedirects);
(<any>window).ga('send', 'pageview');
}

private static isIEorEdge() {
return ['ie', 'edge'].includes(browser().name);
}

ngOnInit(): void {
this.subscribeToSettings();
this.subscribeToIsAuthenticated();
Expand Down Expand Up @@ -77,18 +94,31 @@ export class AppComponent implements OnInit, OnDestroy {
}

private subscribeToSettings() {
if (AppComponent.isIEorEdge()) {
this.store.dispatch(
new ActionSettingsChangeAnimationsPageDisabled({
pageAnimationsDisabled: true
})
);
}
this.store
.select(selectorSettings)
.pipe(takeUntil(this.unsubscribe$))
.subscribe(settings => this.setTheme(settings));
.subscribe(settings => {
this.setTheme(settings);
this.animationService.updateRouteAnimationType(
settings.pageAnimations,
settings.elementsAnimations
);
});
}

private setTheme(settings: SettingsState) {
const { theme, autoNightMode } = settings;
const hours = new Date().getHours();
const effectiveTheme = (autoNightMode && (hours >= 20 || hours <= 6)
? NIGHT_MODE_THEME
: theme
? NIGHT_MODE_THEME
: theme
).toLowerCase();
this.componentCssClass = effectiveTheme;
const classList = this.overlayContainer.getContainerElement().classList;
Expand Down Expand Up @@ -116,7 +146,7 @@ export class AppComponent implements OnInit, OnDestroy {
}

if (event instanceof NavigationEnd) {
this.trackPageView(event);
AppComponent.trackPageView(event);
}
});
}
Expand All @@ -131,9 +161,4 @@ export class AppComponent implements OnInit, OnDestroy {
title ? `${title} - ${env.appName}` : env.appName
);
}

private trackPageView(event: NavigationEnd) {
(<any>window).ga('set', 'page', event.urlAfterRedirects);
(<any>window).ga('send', 'pageview');
}
}
42 changes: 42 additions & 0 deletions src/app/core/animations/animations.service.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { TestBed, inject } from '@angular/core/testing';

import { AnimationsService } from './animations.service';

describe('AnimationsService', () => {
beforeEach(() => {
TestBed.configureTestingModule({
providers: [AnimationsService]
});
});

it(
'should set route animation type to "NONE" by default',
inject([AnimationsService], (service: AnimationsService) => {
expect(AnimationsService.isRouteAnimationType('NONE')).toBe(true);
})
);

it(
'should set route animation type to "ALL"',
inject([AnimationsService], (service: AnimationsService) => {
service.updateRouteAnimationType(true, true);
expect(AnimationsService.isRouteAnimationType('ALL')).toBe(true);
})
);

it(
'should set route animation type to "PAGE"',
inject([AnimationsService], (service: AnimationsService) => {
service.updateRouteAnimationType(true, false);
expect(AnimationsService.isRouteAnimationType('PAGE')).toBe(true);
})
);

it(
'should set route animation type to "ELEMENTS"',
inject([AnimationsService], (service: AnimationsService) => {
service.updateRouteAnimationType(false, true);
expect(AnimationsService.isRouteAnimationType('ELEMENTS')).toBe(true);
})
);
});
25 changes: 25 additions & 0 deletions src/app/core/animations/animations.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { Injectable } from '@angular/core';

@Injectable()
export class AnimationsService {
constructor() {
}

private static routeAnimationType: RouteAnimationType = 'NONE';

static isRouteAnimationType(type: RouteAnimationType) {
return AnimationsService.routeAnimationType === type;
}

updateRouteAnimationType(
pageAnimations: boolean,
elementsAnimations: boolean
) {
AnimationsService.routeAnimationType =
pageAnimations && elementsAnimations
? 'ALL'
: pageAnimations ? 'PAGE' : elementsAnimations ? 'ELEMENTS' : 'NONE';
}
}

export type RouteAnimationType = 'ALL' | 'PAGE' | 'ELEMENTS' | 'NONE';
31 changes: 21 additions & 10 deletions src/app/core/animations/router.transition.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import browser from 'browser-detect';
import {
animate,
query,
Expand All @@ -8,10 +7,11 @@ import {
stagger,
sequence
} from '@angular/animations';
import { AnimationsService } from './animations.service';

export const ANIMATE_ON_ROUTE_ENTER = 'route-enter-staggered';

const ROUTE_TRANSITION: any[] = [
const STEPS_ALL: any[] = [
query(':enter > *', style({ opacity: 0, position: 'fixed' }), {
optional: true
}),
Expand Down Expand Up @@ -59,18 +59,29 @@ const ROUTE_TRANSITION: any[] = [
{ optional: true }
)
];

export const ROUTE_TRANSITION_IE = [ROUTE_TRANSITION[1], ROUTE_TRANSITION[3]];
const STEPS_NONE = [];
const STEPS_PAGE = [STEPS_ALL[0], STEPS_ALL[2]];
const STEPS_ELEMENTS = [STEPS_ALL[1], STEPS_ALL[3]];

export const routerTransition = trigger('routerTransition', [
transition(isNotIEorEdge, ROUTE_TRANSITION),
transition(isIEorEdge, ROUTE_TRANSITION_IE)
transition(isRouteAnimationAll, STEPS_ALL),
transition(isRouteAnimationNone, STEPS_NONE),
transition(isRouteAnimationPage, STEPS_PAGE),
transition(isRouteAnimationElements, STEPS_ELEMENTS)
]);

export function isNotIEorEdge() {
return !isIEorEdge();
export function isRouteAnimationAll() {
return AnimationsService.isRouteAnimationType('ALL');
}

export function isRouteAnimationNone() {
return AnimationsService.isRouteAnimationType('NONE');
}

export function isRouteAnimationPage() {
return AnimationsService.isRouteAnimationType('PAGE');
}

export function isIEorEdge() {
return ['ie', 'edge'].includes(browser().name);
export function isRouteAnimationElements() {
return AnimationsService.isRouteAnimationType('ELEMENTS');
}
3 changes: 2 additions & 1 deletion src/app/core/core.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { LocalStorageService } from './local-storage/local-storage.service';
import { authReducer } from './auth/auth.reducer';
import { AuthEffects } from './auth/auth.effects';
import { AuthGuardService } from './auth/auth-guard.service';
import { AnimationsService } from './animations/animations.service';

export const metaReducers: MetaReducer<any>[] = [initStateFromLocalStorage];

Expand All @@ -36,7 +37,7 @@ if (!environment.production) {
EffectsModule.forRoot([AuthEffects])
],
declarations: [],
providers: [LocalStorageService, AuthGuardService]
providers: [LocalStorageService, AuthGuardService, AnimationsService]
})
export class CoreModule {
constructor(
Expand Down
1 change: 1 addition & 0 deletions src/app/core/index.ts
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export * from './local-storage/local-storage.service';
export * from './animations/router.transition';
export * from './animations/animations.service';
export * from './auth/auth.reducer';
export * from './auth/auth-guard.service';
export * from './core.module';
26 changes: 14 additions & 12 deletions src/app/settings/settings.effects.ts
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Actions, Effect } from '@ngrx/effects';
import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';

import { LocalStorageService } from '@app/core';
import { LocalStorageService, AnimationsService } from '@app/core';

import {
SETTINGS_KEY,
Expand All @@ -16,20 +16,22 @@ import {
export class SettingsEffects {
constructor(
private actions$: Actions<Action>,
private localStorageService: LocalStorageService
private localStorageService: LocalStorageService,
private animationsService: AnimationsService
) {}

@Effect({ dispatch: false })
persistSettings(): Observable<Action> {
return this.actions$
.ofType(SettingsActionTypes.PERSIST)
.pipe(
tap((action: ActionSettingsPersist) =>
this.localStorageService.setItem(
SETTINGS_KEY,
action.payload.settings
)
)
);
return this.actions$.ofType(SettingsActionTypes.PERSIST).pipe(
tap((action: ActionSettingsPersist) => {
const { settings } = action.payload;
const { pageAnimations, elementsAnimations } = settings;
this.localStorageService.setItem(SETTINGS_KEY, settings);
this.animationsService.updateRouteAnimationType(
pageAnimations,
elementsAnimations
);
})
);
}
}
Loading

0 comments on commit 91131b4

Please sign in to comment.