Add host-window.service

This commit is contained in:
Giuseppe Digilio
2017-05-25 17:27:31 +02:00
parent 857fd448d4
commit c5c0bb776b
13 changed files with 1080 additions and 527 deletions

View File

@@ -22,6 +22,7 @@ import { HostWindowResizeAction } from "./shared/host-window.actions";
import { MockTranslateLoader } from "./shared/testing/mock-translate-loader"; import { MockTranslateLoader } from "./shared/testing/mock-translate-loader";
import { GLOBAL_CONFIG, EnvConfig } from '../config'; import { GLOBAL_CONFIG, EnvConfig } from '../config';
import { NativeWindowRef, NativeWindowService } from "./shared/window.service";
let comp: AppComponent; let comp: AppComponent;
let fixture: ComponentFixture<AppComponent>; let fixture: ComponentFixture<AppComponent>;
@@ -42,6 +43,7 @@ describe('App component', () => {
declarations: [AppComponent], // declare the test component declarations: [AppComponent], // declare the test component
providers: [ providers: [
{ provide: GLOBAL_CONFIG, useValue: EnvConfig }, { provide: GLOBAL_CONFIG, useValue: EnvConfig },
{ provide: NativeWindowService, useValue: new NativeWindowRef() },
AppComponent AppComponent
], ],
schemas: [CUSTOM_ELEMENTS_SCHEMA] schemas: [CUSTOM_ELEMENTS_SCHEMA]

View File

@@ -8,9 +8,10 @@ import {
import { TranslateService } from "@ngx-translate/core"; import { TranslateService } from "@ngx-translate/core";
import { HostWindowState } from "./shared/host-window.reducer"; import { HostWindowState } from "./shared/host-window.reducer";
import { Store } from "@ngrx/store"; import { Store } from "@ngrx/store";
import { HostWindowResizeAction } from "./shared/host-window.actions";
import { HostWindowResizeAction } from "./shared/host-window.actions";
import { EnvConfig, GLOBAL_CONFIG, GlobalConfig } from '../config'; import { EnvConfig, GLOBAL_CONFIG, GlobalConfig } from '../config';
import { NativeWindowRef, NativeWindowService } from "./shared/window.service";
@Component({ @Component({
changeDetection: ChangeDetectionStrategy.Default, changeDetection: ChangeDetectionStrategy.Default,
@@ -23,6 +24,7 @@ export class AppComponent implements OnInit {
constructor( constructor(
@Inject(GLOBAL_CONFIG) public EnvConfig: GlobalConfig, @Inject(GLOBAL_CONFIG) public EnvConfig: GlobalConfig,
@Inject(NativeWindowService) private _window: NativeWindowRef,
private translate: TranslateService, private translate: TranslateService,
private store: Store<HostWindowState> private store: Store<HostWindowState>
) { ) {
@@ -33,6 +35,7 @@ export class AppComponent implements OnInit {
} }
ngOnInit() { ngOnInit() {
this.onInit();
const env: string = EnvConfig.production ? "Production" : "Development"; const env: string = EnvConfig.production ? "Production" : "Development";
const color: string = EnvConfig.production ? "red" : "green"; const color: string = EnvConfig.production ? "red" : "green";
console.info(`Environment: %c${env}`, `color: ${color}; font-weight: bold;`); console.info(`Environment: %c${env}`, `color: ${color}; font-weight: bold;`);
@@ -45,4 +48,12 @@ export class AppComponent implements OnInit {
); );
} }
private onInit(): void {
if (typeof this._window !== 'undefined') {
this.store.dispatch(
new HostWindowResizeAction(this._window.nativeWindow.innerWidth, this._window.nativeWindow.innerHeight)
);
}
}
} }

View File

@@ -10,26 +10,10 @@ export class HostWindowResizeAction implements Action {
payload: { payload: {
width: number; width: number;
height: number; height: number;
breakPoint: string;
}; };
constructor(width: number, height: number) { constructor(width: number, height: number) {
let breakPoint = this.getBreakpoint(width); this.payload = { width, height }
this.payload = { width, height, breakPoint }
}
getBreakpoint(windowWidth: number) {
if(windowWidth < 575) {
return 'xs';
} else if (windowWidth >= 576 && windowWidth < 767) {
return 'sm';
} else if (windowWidth >= 768 && windowWidth < 991) {
return 'md';
} else if (windowWidth >= 992 && windowWidth < 1199) {
return 'lg';
} else if (windowWidth >= 1200) {
return 'xl';
}
} }
} }

View File

@@ -13,34 +13,32 @@ class NullAction extends HostWindowResizeAction {
describe('hostWindowReducer', () => { describe('hostWindowReducer', () => {
it("should return the current state when no valid actions have been made", () => { it("should return the current state when no valid actions have been made", () => {
const state = { width: 800, height: 600, breakPoint: 'md' }; const state = { width: 800, height: 600 };
const action = new NullAction(); const action = new NullAction();
const newState = hostWindowReducer(state, action); const newState = hostWindowReducer(state, action);
expect(newState).toEqual(state); expect(newState).toEqual(state);
}); });
it("should start with width = null, height = null and breakPoint = null", () => { it("should start with width = null and height = null", () => {
const action = new NullAction(); const action = new NullAction();
const initialState = hostWindowReducer(undefined, action); const initialState = hostWindowReducer(undefined, action);
expect(initialState.width).toEqual(null); expect(initialState.width).toEqual(null);
expect(initialState.height).toEqual(null); expect(initialState.height).toEqual(null);
expect(initialState.breakPoint).toEqual(null);
}); });
it("should update the width, height and breakPoint in the state in response to a RESIZE action", () => { it("should update the width and height in the state in response to a RESIZE action", () => {
const state = { width: 800, height: 600, breakPoint: 'md' }; const state = { width: 800, height: 600 };
const action = new HostWindowResizeAction(1024, 768); const action = new HostWindowResizeAction(1024, 768);
const newState = hostWindowReducer(state, action); const newState = hostWindowReducer(state, action);
expect(newState.width).toEqual(1024); expect(newState.width).toEqual(1024);
expect(newState.height).toEqual(768); expect(newState.height).toEqual(768);
expect(newState.breakPoint).toEqual('lg');
}); });
it("should perform the RESIZE action without affecting the previous state", () => { it("should perform the RESIZE action without affecting the previous state", () => {
const state = { width: 800, height: 600, breakPoint: 'md' }; const state = { width: 800, height: 600 };
deepFreeze(state); deepFreeze(state);
const action = new HostWindowResizeAction(1024, 768); const action = new HostWindowResizeAction(1024, 768);

View File

@@ -3,13 +3,11 @@ import { HostWindowAction, HostWindowActionTypes } from "./host-window.actions";
export interface HostWindowState { export interface HostWindowState {
width: number; width: number;
height: number; height: number;
breakPoint: string;
} }
const initialState: HostWindowState = { const initialState: HostWindowState = {
width: null, width: null,
height: null, height: null
breakPoint: null
}; };
export const hostWindowReducer = (state = initialState, action: HostWindowAction): HostWindowState => { export const hostWindowReducer = (state = initialState, action: HostWindowAction): HostWindowState => {

View File

@@ -0,0 +1,191 @@
import { HostWindowService } from "./host-window.service";
import { HostWindowState } from "./host-window.reducer";
import { Observable } from "rxjs";
import { Store } from "@ngrx/store";
describe("HostWindowService", () => {
let service: HostWindowService;
let mockStore: any;
let store: Store<HostWindowState>;
describe("", () => {
beforeEach(() => {
let _initialState = { width: 1600, height: 770 };
store = new Store<HostWindowState>(undefined, undefined, Observable.of(_initialState));
service = new HostWindowService(store);
});
it("isXs() should return false with width = 1600", () => {
service.isXs().subscribe((status) => {
expect(status).toBeFalsy();
});
});
it("isSm() should return false with width = 1600", () => {
service.isSm().subscribe((status) => {
expect(status).toBeFalsy();
});
});
it("isMd() should return false with width = 1600", () => {
service.isMd().subscribe((status) => {
expect(status).toBeFalsy();
});
});
it("isLg() should return false with width = 1600", () => {
service.isLg().subscribe((status) => {
expect(status).toBeFalsy();
});
});
it("isXl() should return true with width = 1600", () => {
service.isXl().subscribe((status) => {
expect(status).toBeTruthy();
});
});
});
describe("", () => {
beforeEach(() => {
let _initialState = { width: 1100, height: 770 };
store = new Store<HostWindowState>(undefined, undefined, Observable.of(_initialState));
service = new HostWindowService(store);
});
it("isXs() should return false with width = 1100", () => {
service.isXs().subscribe((status) => {
expect(status).toBeFalsy();
});
});
it("isSm() should return false with width = 1100", () => {
service.isSm().subscribe((status) => {
expect(status).toBeFalsy();
});
});
it("isMd() should return false with width = 1100", () => {
service.isMd().subscribe((status) => {
expect(status).toBeFalsy();
});
});
it("isLg() should return true with width = 1100", () => {
service.isLg().subscribe((status) => {
expect(status).toBeTruthy();
});
});
it("isXl() should return false with width = 1100", () => {
service.isXl().subscribe((status) => {
expect(status).toBeFalsy();
});
});
});
describe("", () => {
beforeEach(() => {
let _initialState = { width: 800, height: 770 };
store = new Store<HostWindowState>(undefined, undefined, Observable.of(_initialState));
service = new HostWindowService(store);
});
it("isXs() should return false with width = 800", () => {
service.isXs().subscribe((status) => {
expect(status).toBeFalsy();
});
});
it("isSm() should return false with width = 800", () => {
service.isSm().subscribe((status) => {
expect(status).toBeFalsy();
});
});
it("isMd() should return true with width = 800", () => {
service.isMd().subscribe((status) => {
expect(status).toBeTruthy();
});
});
it("isLg() should return false with width = 800", () => {
service.isLg().subscribe((status) => {
expect(status).toBeFalsy();
});
});
it("isXl() should return false with width = 800", () => {
service.isXl().subscribe((status) => {
expect(status).toBeFalsy();
});
});
});
describe("", () => {
beforeEach(() => {
let _initialState = { width: 600, height: 770 };
store = new Store<HostWindowState>(undefined, undefined, Observable.of(_initialState));
service = new HostWindowService(store);
});
it("isXs() should return false with width = 600", () => {
service.isXs().subscribe((status) => {
expect(status).toBeFalsy();
});
});
it("isSm() should return true with width = 600", () => {
service.isSm().subscribe((status) => {
expect(status).toBeTruthy();
});
});
it("isMd() should return false with width = 600", () => {
service.isMd().subscribe((status) => {
expect(status).toBeFalsy();
});
});
it("isLg() should return false with width = 600", () => {
service.isLg().subscribe((status) => {
expect(status).toBeFalsy();
});
});
it("isXl() should return false with width = 600", () => {
service.isXl().subscribe((status) => {
expect(status).toBeFalsy();
});
});
});
describe("", () => {
beforeEach(() => {
let _initialState = { width: 400, height: 770 };
store = new Store<HostWindowState>(undefined, undefined, Observable.of(_initialState));
service = new HostWindowService(store);
});
it("isXs() should return true with width = 400", () => {
service.isXs().subscribe((status) => {
expect(status).toBeTruthy();
});
});
it("isSm() should return false with width = 400", () => {
service.isSm().subscribe((status) => {
expect(status).toBeFalsy();
});
});
it("isMd() should return false with width = 400", () => {
service.isMd().subscribe((status) => {
expect(status).toBeFalsy();
});
});
it("isLg() should return false with width = 400", () => {
service.isLg().subscribe((status) => {
expect(status).toBeFalsy();
});
});
it("isXl() should return false with width = 400", () => {
service.isXl().subscribe((status) => {
expect(status).toBeFalsy();
});
});
});
});

View File

@@ -0,0 +1,58 @@
import { HostWindowState } from "./host-window.reducer";
import { Injectable } from "@angular/core";
import { Store } from "@ngrx/store";
import { Observable } from "rxjs/Observable";
import { hasValue } from "./empty.util";
//TODO ideally we should get these from sass somehow
export enum GridBreakpoint {
XS = 0,
SM = 576,
MD = 768,
LG = 992,
XL = 1200
}
@Injectable()
export class HostWindowService {
constructor(
private store: Store<HostWindowState>
) {
}
private getWidthObs(): Observable<number> {
return this.store.select<number>('hostWindow', 'width')
.filter(width => hasValue(width));
}
isXs(): Observable<boolean> {
return this.getWidthObs()
.map(width => width < GridBreakpoint.SM)
.distinctUntilChanged();
}
isSm(): Observable<boolean> {
return this.getWidthObs()
.map(width => width >= GridBreakpoint.SM && width < GridBreakpoint.MD)
.distinctUntilChanged();
}
isMd(): Observable<boolean> {
return this.getWidthObs()
.map(width => width >= GridBreakpoint.MD && width < GridBreakpoint.LG)
.distinctUntilChanged();
}
isLg(): Observable<boolean> {
return this.getWidthObs()
.map(width => width >= GridBreakpoint.LG && width < GridBreakpoint.XL)
.distinctUntilChanged();
}
isXl(): Observable<boolean> {
return this.getWidthObs()
.map(width => width >= GridBreakpoint.XL)
.distinctUntilChanged();
}
}

View File

@@ -23,10 +23,10 @@
[collectionSize]="collectionSize" [collectionSize]="collectionSize"
[disabled]="paginationOptions.disabled" [disabled]="paginationOptions.disabled"
[ellipses]="paginationOptions.ellipses" [ellipses]="paginationOptions.ellipses"
[maxSize]="(windowBreakPoint.breakPoint == 'xs')?5:paginationOptions.maxSize" [maxSize]="(isXs)?5:paginationOptions.maxSize"
[(page)]="currentPage" [(page)]="currentPage"
(pageChange)="doPageChange($event)" (pageChange)="doPageChange($event)"
[pageSize]="pageSize" [pageSize]="pageSize"
[rotate]="paginationOptions.rotate" [rotate]="paginationOptions.rotate"
[size]="(windowBreakPoint.breakPoint == 'xs')?'sm':paginationOptions.size"></ngb-pagination> [size]="(isXs)?'sm':paginationOptions.size"></ngb-pagination>
</div> </div>

View File

@@ -3,7 +3,7 @@ import {
async, async,
ComponentFixture, ComponentFixture,
inject, inject,
TestBed, fakeAsync, tick, getTestBed TestBed, fakeAsync, tick
} from '@angular/core/testing'; } from '@angular/core/testing';
import { import {
Component, Component,
@@ -11,11 +11,12 @@ import {
DebugElement DebugElement
} from "@angular/core"; } from "@angular/core";
import { ActivatedRoute, Router } from "@angular/router"; import { ActivatedRoute, Router } from "@angular/router";
import { RouterTestingModule } from '@angular/router/testing';
import { By } from '@angular/platform-browser'; import { By } from '@angular/platform-browser';
import { Observable } from "rxjs";
import { RouterTestingModule } from '@angular/router/testing';
import Spy = jasmine.Spy; import Spy = jasmine.Spy;
import { TranslateModule, TranslateLoader } from '@ngx-translate/core'; import { TranslateModule, TranslateLoader } from '@ngx-translate/core';
import { Store, StoreModule } from "@ngrx/store"; import { StoreModule } from "@ngrx/store";
// Load the implementations that should be tested // Load the implementations that should be tested
import { CommonModule } from '@angular/common'; import { CommonModule } from '@angular/common';
@@ -28,8 +29,9 @@ import { PaginationOptions } from '../../core/cache/models/pagination-options.mo
import { MockTranslateLoader } from "../testing/mock-translate-loader"; import { MockTranslateLoader } from "../testing/mock-translate-loader";
import { GLOBAL_CONFIG, EnvConfig } from '../../../config'; import { GLOBAL_CONFIG, EnvConfig } from '../../../config';
import { MockStore, MockAction } from "../testing/mock-store";
import { ActivatedRouteStub, RouterStub } from "../testing/router-stubs"; import { ActivatedRouteStub, RouterStub } from "../testing/router-stubs";
import { HostWindowService } from "../host-window.service";
function createTestComponent<T>(html: string, type: {new (...args: any[]): T}): ComponentFixture<T> { function createTestComponent<T>(html: string, type: {new (...args: any[]): T}): ComponentFixture<T> {
TestBed.overrideComponent(type, { TestBed.overrideComponent(type, {
@@ -112,19 +114,19 @@ describe('Pagination component', () => {
let testFixture: ComponentFixture<TestComponent>; let testFixture: ComponentFixture<TestComponent>;
let de: DebugElement; let de: DebugElement;
let html; let html;
let mockStore: any; let hostWindowServiceStub: HostWindowServiceStub;
let activatedRouteStub: ActivatedRouteStub; let activatedRouteStub: ActivatedRouteStub;
let routerStub: RouterStub; let routerStub: RouterStub;
//Define initial state and test state //Define initial state and test state
let _initialState = { width: 1600, height: 770, breakPoint: 'xl' }; let _initialState = { width: 1600, height: 770 };
// async beforeEach // async beforeEach
beforeEach(async(() => { beforeEach(async(() => {
activatedRouteStub = new ActivatedRouteStub(); activatedRouteStub = new ActivatedRouteStub();
routerStub = new RouterStub(); routerStub = new RouterStub();
mockStore = new MockStore(_initialState); hostWindowServiceStub = new HostWindowServiceStub(_initialState.width);
TestBed.configureTestingModule({ TestBed.configureTestingModule({
imports: [CommonModule, StoreModule.provideStore({}), TranslateModule.forRoot({ imports: [CommonModule, StoreModule.provideStore({}), TranslateModule.forRoot({
@@ -141,7 +143,7 @@ describe('Pagination component', () => {
{ provide: ActivatedRoute, useValue: activatedRouteStub }, { provide: ActivatedRoute, useValue: activatedRouteStub },
{ provide: GLOBAL_CONFIG, useValue: EnvConfig }, { provide: GLOBAL_CONFIG, useValue: EnvConfig },
{ provide: Router, useValue: routerStub }, { provide: Router, useValue: routerStub },
{ provide: Store, useValue: mockStore }, { provide: HostWindowService, useValue: hostWindowServiceStub },
PaginationComponent PaginationComponent
], ],
schemas: [CUSTOM_ELEMENTS_SCHEMA] schemas: [CUSTOM_ELEMENTS_SCHEMA]
@@ -285,12 +287,12 @@ describe('Pagination component', () => {
it('should respond to windows resize', () => { it('should respond to windows resize', () => {
let paginationComponent: PaginationComponent = testFixture let paginationComponent: PaginationComponent = testFixture
.debugElement.query(By.css('ds-pagination')).references['p']; .debugElement.query(By.css('ds-pagination')).references['p'];
mockStore = testFixture.debugElement.injector.get(Store); hostWindowServiceStub = testFixture.debugElement.injector.get(HostWindowService);
mockStore.nextState({ width: 400, height: 770, breakPoint: 'xs' }); hostWindowServiceStub.setWidth(400);
mockStore.select('hostWindow').subscribe((state) => { hostWindowServiceStub.isXs().subscribe((status) => {
paginationComponent.windowBreakPoint = state; paginationComponent.isXs = status;
testFixture.detectChanges(); testFixture.detectChanges();
expectPages(testFixture, ['-«', '+1', '2', '3', '4', '5', '-...', '10', '»']); expectPages(testFixture, ['-«', '+1', '2', '3', '4', '5', '-...', '10', '»']);
de = testFixture.debugElement.query(By.css('ul.pagination')); de = testFixture.debugElement.query(By.css('ul.pagination'));
@@ -300,7 +302,7 @@ describe('Pagination component', () => {
}); });
// declare a test component // declare a test component
@Component({selector: 'test-cmp', template: ''}) @Component({selector: 'ds-test-cmp', template: ''})
class TestComponent { class TestComponent {
collection: string[] = []; collection: string[] = [];
@@ -321,3 +323,21 @@ class TestComponent {
this.paginationOptions.pageSize = pageSize; this.paginationOptions.pageSize = pageSize;
} }
} }
// declare a stub service
class HostWindowServiceStub {
private width: number;
constructor(width) {
this.setWidth(width);
}
setWidth(width) {
this.width = width;
}
isXs(): Observable<boolean> {
return Observable.of(this.width < 576);
}
}

View File

@@ -11,11 +11,11 @@ import {
import { ActivatedRoute, Router } from '@angular/router'; import { ActivatedRoute, Router } from '@angular/router';
import { isNumeric } from "rxjs/util/isNumeric"; import { isNumeric } from "rxjs/util/isNumeric";
import 'rxjs/add/operator/switchMap'; import 'rxjs/add/operator/switchMap';
import { Store } from "@ngrx/store";
import { Observable } from "rxjs"; import { Observable } from "rxjs";
// It is necessary to use ng2-pagination // It is necessary to use ng2-pagination
import { DEFAULT_TEMPLATE, DEFAULT_STYLES } from 'ng2-pagination/dist/template'; import { DEFAULT_TEMPLATE, DEFAULT_STYLES } from 'ng2-pagination/dist/template';
import { HostWindowService } from "../host-window.service";
import { HostWindowState } from "../host-window.reducer"; import { HostWindowState } from "../host-window.reducer";
import { PaginationOptions } from '../../core/cache/models/pagination-options.model'; import { PaginationOptions } from '../../core/cache/models/pagination-options.model';
@@ -69,6 +69,11 @@ export class PaginationComponent implements OnDestroy, OnInit {
*/ */
private id: string; private id: string;
/**
* A boolean that indicate if is an extra small devices viewport.
*/
public isXs: boolean;
/** /**
* Number of items per page. * Number of items per page.
*/ */
@@ -102,17 +107,13 @@ export class PaginationComponent implements OnDestroy, OnInit {
*/ */
private stateSubscription: any; private stateSubscription: any;
/**
* Contains current HostWindowState
*/
public windowBreakPoint: HostWindowState;
/** /**
* Method provided by Angular. Invoked after the constructor. * Method provided by Angular. Invoked after the constructor.
*/ */
ngOnInit() { ngOnInit() {
this.stateSubscription = this.hostWindow.subscribe((state: HostWindowState) => { this.stateSubscription = this.hostWindowService.isXs()
this.windowBreakPoint = state; .subscribe((status: boolean) => {
this.isXs = status;
}); });
this.checkConfig(this.paginationOptions); this.checkConfig(this.paginationOptions);
this.id = this.paginationOptions.id || null; this.id = this.paginationOptions.id || null;
@@ -150,9 +151,8 @@ export class PaginationComponent implements OnDestroy, OnInit {
constructor( constructor(
private route: ActivatedRoute, private route: ActivatedRoute,
private router: Router, private router: Router,
private store: Store<HostWindowState> public hostWindowService: HostWindowService
){ ){
this.hostWindow = this.store.select<HostWindowState>('hostWindow');
} }
/** /**
@@ -231,8 +231,8 @@ export class PaginationComponent implements OnDestroy, OnInit {
* The paginate options object. * The paginate options object.
*/ */
private checkConfig(paginateOptions: any) { private checkConfig(paginateOptions: any) {
var required = ['id', 'currentPage', 'pageSize', 'pageSizeOptions']; let required = ['id', 'currentPage', 'pageSize', 'pageSizeOptions'];
var missing = required.filter(function (prop) { return !(prop in paginateOptions); }); let missing = required.filter(function (prop) { return !(prop in paginateOptions); });
if (0 < missing.length) { if (0 < missing.length) {
throw new Error("Paginate: Argument is missing the following required properties: " + missing.join(', ')); throw new Error("Paginate: Argument is missing the following required properties: " + missing.join(', '));
} }

View File

@@ -12,6 +12,8 @@ import { PaginationComponent } from "./pagination/pagination.component";
import { FileSizePipe } from "./utils/file-size-pipe"; import { FileSizePipe } from "./utils/file-size-pipe";
import { ThumbnailComponent } from "../thumbnail/thumbnail.component"; import { ThumbnailComponent } from "../thumbnail/thumbnail.component";
import { SafeUrlPipe } from "./utils/safe-url-pipe"; import { SafeUrlPipe } from "./utils/safe-url-pipe";
import { HostWindowService } from "./host-window.service";
import { NativeWindowFactory, NativeWindowService } from "./window.service";
const MODULES = [ const MODULES = [
// Do NOT include UniversalModule, HttpModule, or JsonpModule here // Do NOT include UniversalModule, HttpModule, or JsonpModule here
@@ -37,7 +39,9 @@ const COMPONENTS = [
]; ];
const PROVIDERS = [ const PROVIDERS = [
ApiService ApiService,
HostWindowService,
{ provide: NativeWindowService, useFactory: NativeWindowFactory }
]; ];
@NgModule({ @NgModule({
@@ -52,6 +56,9 @@ const PROVIDERS = [
...MODULES, ...MODULES,
...PIPES, ...PIPES,
...COMPONENTS ...COMPONENTS
],
providers: [
...PROVIDERS
] ]
}) })
export class SharedModule { export class SharedModule {

View File

@@ -0,0 +1,18 @@
import { OpaqueToken } from '@angular/core';
export const NativeWindowService = new OpaqueToken('NativeWindowService');
export class NativeWindowRef {
get nativeWindow (): any {
if (typeof window !== 'undefined') {
return window;
} else {
return false;
}
}
}
export function NativeWindowFactory() {
return new NativeWindowRef();
}

1206
yarn.lock

File diff suppressed because it is too large Load Diff