fix(ssr): fix angular global window and document references

This commit is contained in:
Adam Bradley
2019-02-25 16:43:41 -06:00
committed by GitHub
parent ceaef7eed2
commit f44c17e03b
19 changed files with 200 additions and 214 deletions

View File

@ -1,4 +1,5 @@
import { Injectable } from '@angular/core';
import { DOCUMENT } from '@angular/common';
import { Inject, Injectable } from '@angular/core';
import { BackButtonEventDetail, Platforms, getPlatforms, isPlatform } from '@ionic/core';
import { Subject, Subscription } from 'rxjs';
@ -12,6 +13,7 @@ export interface BackButtonEmitter extends Subject<BackButtonEventDetail> {
export class Platform {
private _readyPromise: Promise<string>;
private win: any;
/**
* @hidden
@ -40,22 +42,24 @@ export class Platform {
*/
resize = new Subject<void>();
constructor() {
constructor(@Inject(DOCUMENT) private doc: any) {
this.win = doc.defaultView;
this.backButton.subscribeWithPriority = function(priority, callback) {
return this.subscribe(ev => {
ev.register(priority, callback);
});
};
proxyEvent(this.pause, document, 'pause');
proxyEvent(this.resume, document, 'resume');
proxyEvent(this.backButton, document, 'ionBackButton');
proxyEvent(this.resize, window, 'resize');
proxyEvent(this.pause, doc, 'pause');
proxyEvent(this.resume, doc, 'resume');
proxyEvent(this.backButton, doc, 'ionBackButton');
proxyEvent(this.resize, this.win, 'resize');
let readyResolve: (value: string) => void;
this._readyPromise = new Promise(res => { readyResolve = res; });
if ((window as any)['cordova']) {
document.addEventListener('deviceready', () => {
if (this.win && this.win['cordova']) {
doc.addEventListener('deviceready', () => {
readyResolve('cordova');
}, { once: true });
} else {
@ -106,7 +110,7 @@ export class Platform {
*
*/
is(platformName: Platforms): boolean {
return isPlatform(window, platformName);
return isPlatform(this.win, platformName);
}
/**
@ -129,7 +133,7 @@ export class Platform {
* ```
*/
platforms(): string[] {
return getPlatforms(window);
return getPlatforms(this.win);
}
/**
@ -172,14 +176,14 @@ export class Platform {
* [W3C: Structural markup and right-to-left text in HTML](http://www.w3.org/International/questions/qa-html-dir)
*/
get isRTL(): boolean {
return document.dir === 'rtl';
return this.doc.dir === 'rtl';
}
/**
* Get the query string parameter
*/
getQueryParam(key: string): string | null {
return readQueryParam(window.location.href, key);
return readQueryParam(this.win.location.href, key);
}
/**
@ -193,45 +197,48 @@ export class Platform {
* Returns `true` if the app is in portait mode.
*/
isPortrait(): boolean {
return window.matchMedia('(orientation: portrait)').matches;
return this.win.matchMedia && this.win.matchMedia('(orientation: portrait)').matches;
}
testUserAgent(expression: string): boolean {
return navigator.userAgent.indexOf(expression) >= 0;
const nav = this.win.navigator;
return !!(nav && nav.userAgent && nav.userAgent.indexOf(expression) >= 0);
}
/**
* Get the current url.
*/
url() {
return window.location.href;
return this.win.location.href;
}
/**
* Gets the width of the platform's viewport using `window.innerWidth`.
*/
width() {
return window.innerWidth;
return this.win.innerWidth;
}
/**
* Gets the height of the platform's viewport using `window.innerHeight`.
*/
height(): number {
return window.innerHeight;
return this.win.innerHeight;
}
}
function readQueryParam(url: string, key: string) {
const readQueryParam = (url: string, key: string) => {
key = key.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]');
const regex = new RegExp('[\\?&]' + key + '=([^&#]*)');
const results = regex.exec(url);
return results ? decodeURIComponent(results[1].replace(/\+/g, ' ')) : null;
}
};
function proxyEvent<T>(emitter: Subject<T>, el: EventTarget, eventName: string) {
el.addEventListener(eventName, (ev: Event | undefined | null) => {
// ?? cordova might emit "null" events
emitter.next(ev != null ? (ev as any).detail as T : undefined);
});
}
const proxyEvent = <T>(emitter: Subject<T>, el: EventTarget, eventName: string) => {
if ((el as any)) {
el.addEventListener(eventName, (ev: Event | undefined | null) => {
// ?? cordova might emit "null" events
emitter.next(ev != null ? (ev as any).detail as T : undefined);
});
}
};