diff --git a/nativescript-angular/dom-adapter.ts b/nativescript-angular/dom-adapter.ts index cdca10553..3964978b3 100644 --- a/nativescript-angular/dom-adapter.ts +++ b/nativescript-angular/dom-adapter.ts @@ -49,12 +49,6 @@ export class NativeScriptElementSchemaRegistry extends ElementSchemaRegistry { } } -export class NativeScriptSanitizer extends Sanitizer { - sanitize(context: SecurityContext, value: string): string { - return value; - } -} - export class NativeScriptDomAdapter extends Parse5DomAdapter { static makeCurrent() { rendererLog("Setting DOM"); diff --git a/nativescript-angular/index.ts b/nativescript-angular/index.ts index 751a09787..ef3f466dc 100644 --- a/nativescript-angular/index.ts +++ b/nativescript-angular/index.ts @@ -1,4 +1,5 @@ export * from "./platform"; +export * from "./platform-static"; export * from "./router"; export * from "./forms"; export * from "./http"; diff --git a/nativescript-angular/nativescript.module.ts b/nativescript-angular/nativescript.module.ts index 4278571d4..4f5e7a93a 100644 --- a/nativescript-angular/nativescript.module.ts +++ b/nativescript-angular/nativescript.module.ts @@ -14,13 +14,11 @@ import { ErrorHandler, Renderer, RootRenderer, - Sanitizer, - NgModule, NO_ERRORS_SCHEMA, CUSTOM_ELEMENTS_SCHEMA + NgModule, NO_ERRORS_SCHEMA, } from '@angular/core'; import { defaultPageProvider, defaultFrameProvider, defaultDeviceProvider } from "./platform-providers"; -import { NativeScriptSanitizer } from './dom-adapter'; import { NS_DIRECTIVES } from './directives'; import * as nativescriptIntl from "nativescript-intl"; @@ -45,7 +43,6 @@ export function errorHandlerFactory() { { provide: RootRenderer, useClass: NativeScriptRootRenderer }, NativeScriptRenderer, { provide: Renderer, useClass: NativeScriptRenderer }, - { provide: Sanitizer, useClass: NativeScriptSanitizer }, ModalDialogService ], entryComponents: [ diff --git a/nativescript-angular/platform-common.ts b/nativescript-angular/platform-common.ts new file mode 100644 index 000000000..5b01c149e --- /dev/null +++ b/nativescript-angular/platform-common.ts @@ -0,0 +1,194 @@ +// Initial imports and polyfills +import 'globals'; +import './zone.js/dist/zone-nativescript'; +import 'reflect-metadata'; +import './polyfills/array'; +import './polyfills/console'; + +import { + Type, + Injector, + CompilerOptions, + PlatformRef, + NgModuleFactory, + NgModuleRef, + EventEmitter, + Provider, + Sanitizer, + OpaqueToken, +} from '@angular/core'; + +import { rendererLog, rendererError } from "./trace"; +import { PAGE_FACTORY, PageFactory, defaultPageFactoryProvider } from './platform-providers'; + +import * as application from "application"; +import { topmost, NavigationEntry } from "ui/frame"; +import { Page } from 'ui/page'; +import { TextView } from 'ui/text-view'; + +import * as nativescriptIntl from "nativescript-intl"; +global.Intl = nativescriptIntl; + +export const onBeforeLivesync = new EventEmitter>(); +export const onAfterLivesync = new EventEmitter>(); +let lastBootstrappedModule: WeakRef>; +type BootstrapperAction = () => Promise>; + +interface BootstrapParams { + appModuleType: Type; + appOptions?: AppOptions; +} + +export interface AppOptions { + bootInExistingPage: boolean; + cssFile?: string; + startPageActionBarHidden?: boolean; +} + +export type PlatformFactory = (extraProviders?: Provider[]) => PlatformRef; + +export class NativeScriptSanitizer extends Sanitizer { + sanitize(context: any, value: string): string { + return value; + } +} + +export const COMMON_PROVIDERS = [ + defaultPageFactoryProvider, + { provide: Sanitizer, useClass: NativeScriptSanitizer }, +]; + +export class NativeScriptPlatformRef extends PlatformRef { + private _bootstrapper: BootstrapperAction; + + constructor(private platform: PlatformRef, private appOptions?: AppOptions) { + super(); + } + + bootstrapModuleFactory(moduleFactory: NgModuleFactory): Promise> { + this._bootstrapper = () => this.platform.bootstrapModuleFactory(moduleFactory); + + this.bootstrapApp(); + + return null; //Make the compiler happy + } + + bootstrapModule(moduleType: Type, compilerOptions: CompilerOptions | CompilerOptions[] = []): Promise> { + this._bootstrapper = () => this.platform.bootstrapModule(moduleType, compilerOptions); + + this.bootstrapApp(); + + return null; //Make the compiler happy + } + + private bootstrapApp() { + global.__onLiveSyncCore = () => this.livesyncModule(); + + const mainPageEntry = this.createNavigationEntry(this._bootstrapper); + + application.start(mainPageEntry); + } + + livesyncModule(): void { + rendererLog("ANGULAR LiveSync Started"); + + onBeforeLivesync.next(lastBootstrappedModule ? lastBootstrappedModule.get() : null); + + const mainPageEntry = this.createNavigationEntry( + this._bootstrapper, + compRef => onAfterLivesync.next(compRef), + error => onAfterLivesync.error(error), + true + ); + mainPageEntry.animated = false; + mainPageEntry.clearHistory = true; + + const frame = topmost(); + if (frame) { + if (frame.currentPage && frame.currentPage.modal) { + frame.currentPage.modal.closeModal(); + } + frame.navigate(mainPageEntry); + } + } + + onDestroy(callback: () => void): void { + this.platform.onDestroy(callback); + } + + get injector(): Injector { + return this.platform.injector; + }; + + destroy(): void { + this.platform.destroy(); + } + + get destroyed(): boolean { + return this.platform.destroyed; + } + + private createNavigationEntry( + bootstrapAction: BootstrapperAction, + resolve?: (comp: NgModuleRef) => void, + reject?: (e: Error) => void, + isLivesync: boolean = false, + isReboot: boolean = false): NavigationEntry { + + const pageFactory: PageFactory = this.platform.injector.get(PAGE_FACTORY); + + const navEntry: NavigationEntry = { + create: (): Page => { + let page = pageFactory({ isBootstrap: true, isLivesync }); + if (this.appOptions) { + page.actionBarHidden = this.appOptions.startPageActionBarHidden; + } + + let onLoadedHandler = function (args) { + page.off('loaded', onLoadedHandler); + //profiling.stop('application-start'); + rendererLog('Page loaded'); + + //profiling.start('ng-bootstrap'); + rendererLog('BOOTSTRAPPING...'); + bootstrapAction().then((moduleRef) => { + //profiling.stop('ng-bootstrap'); + rendererLog('ANGULAR BOOTSTRAP DONE.'); + lastBootstrappedModule = new WeakRef(moduleRef); + + if (resolve) { + resolve(moduleRef); + } + return moduleRef; + }, (err) => { + rendererError('ERROR BOOTSTRAPPING ANGULAR'); + let errorMessage = err.message + "\n\n" + err.stack; + rendererError(errorMessage); + + let view = new TextView(); + view.text = errorMessage; + page.content = view; + + if (reject) { + reject(err); + } + }); + }; + + page.on('loaded', onLoadedHandler); + + return page; + } + }; + + if (isReboot) { + navEntry.animated = false; + navEntry.clearHistory = true; + } + + return navEntry; + } + + liveSyncApp() { + } +} diff --git a/nativescript-angular/platform-static.ts b/nativescript-angular/platform-static.ts new file mode 100644 index 000000000..9c9d7c32e --- /dev/null +++ b/nativescript-angular/platform-static.ts @@ -0,0 +1,17 @@ +// Always import platform-common first - because polyfills +import { NativeScriptPlatformRef, AppOptions, COMMON_PROVIDERS, PlatformFactory } from "./platform-common"; + +import { platformCore, PlatformRef, createPlatformFactory } from '@angular/core'; + +// "Static" platform +const _platformNativeScript: PlatformFactory = createPlatformFactory( + platformCore, 'nativeScript', [...COMMON_PROVIDERS]); + +export function platformNativeScript(options?: AppOptions, extraProviders?: any[]): PlatformRef { + //Return raw platform to advanced users only if explicitly requested + if (options && options.bootInExistingPage === true) { + return _platformNativeScript(extraProviders); + } else { + return new NativeScriptPlatformRef(_platformNativeScript(extraProviders), options); + } +} diff --git a/nativescript-angular/platform.ts b/nativescript-angular/platform.ts index e3a889070..25fb55b5c 100644 --- a/nativescript-angular/platform.ts +++ b/nativescript-angular/platform.ts @@ -1,9 +1,5 @@ -import 'globals'; -import './zone.js/dist/zone-nativescript'; - -import 'reflect-metadata'; -import './polyfills/array'; -import './polyfills/console'; +// Always import platform-common first - because polyfills +import { NativeScriptPlatformRef, AppOptions, PlatformFactory, COMMON_PROVIDERS } from "./platform-common"; import { ElementSchemaRegistry, @@ -11,43 +7,20 @@ import { COMPILER_PROVIDERS, platformCoreDynamic } from '@angular/compiler'; -import { Provider, platformCore } from '@angular/core'; + import { - Type, - Injector, - CompilerOptions, COMPILER_OPTIONS, + Sanitizer, PlatformRef, - NgModuleFactory, - NgModuleRef, - EventEmitter, OpaqueToken, createPlatformFactory } from '@angular/core'; -import * as application from "application"; -import { topmost, NavigationEntry } from "ui/frame"; -import { Page } from 'ui/page'; -import { rendererLog, rendererError } from "./trace"; -import { TextView } from 'ui/text-view'; import { NativeScriptElementSchemaRegistry } from './dom-adapter'; import { FileSystemResourceLoader } from './resource-loader'; -import { PAGE_FACTORY, PageFactory, defaultPageFactoryProvider } from './platform-providers'; - -import * as nativescriptIntl from "nativescript-intl"; -global.Intl = nativescriptIntl; - -type PlatformFactory = (extraProviders?: Provider[]) => PlatformRef; - export { NativeScriptModule } from "./nativescript.module"; -export interface AppOptions { - bootInExistingPage: boolean, - cssFile?: string; - startPageActionBarHidden?: boolean; -} - export const NS_COMPILER_PROVIDERS = [ COMPILER_PROVIDERS, { @@ -59,154 +32,10 @@ export const NS_COMPILER_PROVIDERS = [ ] }, multi: true - } + }, ]; -const COMMON_PROVIDERS = [ - defaultPageFactoryProvider, -]; - -export const onBeforeLivesync = new EventEmitter>(); -export const onAfterLivesync = new EventEmitter>(); - -type BootstrapperAction = () => Promise>; - -let lastBootstrappedModule: WeakRef>; -interface BootstrapParams { - appModuleType: Type, - appOptions?: AppOptions -} - -class NativeScriptPlatformRef extends PlatformRef { - private _bootstrapper: BootstrapperAction; - - constructor(private platform: PlatformRef, private appOptions?: AppOptions) { - super(); - } - - bootstrapModuleFactory(moduleFactory: NgModuleFactory): Promise> { - this._bootstrapper = () => this.platform.bootstrapModuleFactory(moduleFactory); - - this.bootstrapApp(); - - return null; //Make the compiler happy - } - - bootstrapModule(moduleType: Type, compilerOptions: CompilerOptions | CompilerOptions[] = []): Promise> { - this._bootstrapper = () => this.platform.bootstrapModule(moduleType, compilerOptions); - - this.bootstrapApp(); - - return null; //Make the compiler happy - } - - private bootstrapApp() { - global.__onLiveSyncCore = () => this.livesyncModule(); - - const mainPageEntry = this.createNavigationEntry(this._bootstrapper); - - application.start(mainPageEntry); - } - - livesyncModule(): void { - rendererLog("ANGULAR LiveSync Started"); - - onBeforeLivesync.next(lastBootstrappedModule ? lastBootstrappedModule.get() : null); - - const mainPageEntry = this.createNavigationEntry( - this._bootstrapper, - compRef => onAfterLivesync.next(compRef), - error => onAfterLivesync.error(error), - true - ); - mainPageEntry.animated = false; - mainPageEntry.clearHistory = true; - - const frame = topmost(); - if (frame) { - if (frame.currentPage && frame.currentPage.modal) { - frame.currentPage.modal.closeModal(); - } - frame.navigate(mainPageEntry); - } - } - - onDestroy(callback: () => void): void { - this.platform.onDestroy(callback); - } - - get injector(): Injector { - return this.platform.injector; - }; - - destroy(): void { - this.platform.destroy(); - } - - get destroyed(): boolean { - return this.platform.destroyed; - } - - private createNavigationEntry(bootstrapAction: BootstrapperAction, resolve?: (comp: NgModuleRef) => void, reject?: (e: Error) => void, isLivesync: boolean = false, isReboot: boolean = false): NavigationEntry { - const pageFactory: PageFactory = this.platform.injector.get(PAGE_FACTORY); - - const navEntry: NavigationEntry = { - create: (): Page => { - let page = pageFactory({ isBootstrap: true, isLivesync }); - if (this.appOptions) { - page.actionBarHidden = this.appOptions.startPageActionBarHidden; - } - - let onLoadedHandler = function (args) { - page.off('loaded', onLoadedHandler); - //profiling.stop('application-start'); - rendererLog('Page loaded'); - - //profiling.start('ng-bootstrap'); - rendererLog('BOOTSTRAPPING...'); - bootstrapAction().then((moduleRef) => { - //profiling.stop('ng-bootstrap'); - rendererLog('ANGULAR BOOTSTRAP DONE.'); - lastBootstrappedModule = new WeakRef(moduleRef); - - if (resolve) { - resolve(moduleRef); - } - return moduleRef; - }, (err) => { - rendererError('ERROR BOOTSTRAPPING ANGULAR'); - let errorMessage = err.message + "\n\n" + err.stack; - rendererError(errorMessage); - - let view = new TextView(); - view.text = errorMessage; - page.content = view; - - if (reject) { - reject(err); - } - }); - }; - - page.on('loaded', onLoadedHandler); - - return page; - } - }; - - if (isReboot) { - navEntry.animated = false; - navEntry.clearHistory = true; - } - - return navEntry; - } - - liveSyncApp() { - } -} - -// Dynamic platfrom +// Dynamic platform const _platformNativeScriptDynamic: PlatformFactory = createPlatformFactory( platformCoreDynamic, 'nativeScriptDynamic', [...COMMON_PROVIDERS, ...NS_COMPILER_PROVIDERS]); @@ -217,17 +46,4 @@ export function platformNativeScriptDynamic(options?: AppOptions, extraProviders } else { return new NativeScriptPlatformRef(_platformNativeScriptDynamic(extraProviders), options); } -} - -// "Static" platform -const _platformNativeScript: PlatformFactory = createPlatformFactory( - platformCore, 'nativeScript', [...COMMON_PROVIDERS]); - -export function platformNativeScript(options?: AppOptions, extraProviders?: any[]): PlatformRef { - //Return raw platform to advanced users only if explicitly requested - if (options && options.bootInExistingPage === true) { - return _platformNativeScript(extraProviders); - } else { - return new NativeScriptPlatformRef(_platformNativeScript(extraProviders), options); - } -} +} \ No newline at end of file diff --git a/nativescript-angular/router/ns-router-link-active.ts b/nativescript-angular/router/ns-router-link-active.ts index 679007535..94af17ce5 100644 --- a/nativescript-angular/router/ns-router-link-active.ts +++ b/nativescript-angular/router/ns-router-link-active.ts @@ -56,7 +56,7 @@ export class NSRouterLinkActive implements OnChanges, OnDestroy, AfterContentIni private classes: string[] = []; private subscription: Subscription; - @Input() private nsRouterLinkActiveOptions: { exact: boolean } = { exact: false }; + @Input() nsRouterLinkActiveOptions: { exact: boolean } = { exact: false }; constructor(private router: Router, private element: ElementRef, private renderer: Renderer) { this.subscription = router.events.subscribe(s => { diff --git a/nativescript-angular/router/page-router-outlet.ts b/nativescript-angular/router/page-router-outlet.ts index 0d8852b2c..baa9261ff 100644 --- a/nativescript-angular/router/page-router-outlet.ts +++ b/nativescript-angular/router/page-router-outlet.ts @@ -13,7 +13,7 @@ import { DetachedLoader } from "../common/detached-loader"; import { ViewUtil } from "../view-util"; import { Frame } from "ui/frame"; import { Page, NavigatedData } from "ui/page"; -import { BehaviorSubject } from "rxjs"; +import { BehaviorSubject } from "rxjs/BehaviorSubject"; interface CacheItem { componentRef: ComponentRef;