Skip to content

Fast livesync #312

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 30, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
134 changes: 95 additions & 39 deletions nativescript-angular/application.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import './polyfills/array';
import {rendererLog, rendererError} from "./trace";
import {SanitizationService} from '@angular/core/src/security';
import {isPresent, Type, print} from '@angular/core/src/facade/lang';
import {ReflectiveInjector, coreLoadAndBootstrap, createPlatform,
import {ReflectiveInjector, coreLoadAndBootstrap, createPlatform, EventEmitter,
getPlatform, assertPlatform, ComponentRef, PlatformRef, PLATFORM_DIRECTIVES, PLATFORM_PIPES} from '@angular/core';
import {bind, provide, Provider} from '@angular/core/src/di';

Expand All @@ -28,6 +28,8 @@ import {NS_DIRECTIVES} from './directives';
import {Page} from 'ui/page';
import {TextView} from 'ui/text-view';
import application = require('application');
import {topmost, NavigationEntry} from "ui/frame";
import {Observable} from "rxjs";

export type ProviderArray = Array<Type | Provider | any[]>;

Expand All @@ -48,9 +50,20 @@ class ConsoleLogger {
logGroupEnd() { }
}

interface BootstrapParams {
appComponentType: Type,
customProviders?: ProviderArray,
appOptions?: AppOptions
}
var bootstrapCache: BootstrapParams

var lastBootstrappedApp: WeakRef<ComponentRef<any>>;
export const onBeforeLivesync = new EventEmitter<ComponentRef<any>>();
export const onAfterLivesync = new EventEmitter<ComponentRef<any>>();

// See: https://github.com/angular/angular/commit/1745366530266d298306b995ecd23dabd8569e28
export const NS_COMPILER_PROVIDERS: ProviderArray = [
COMPILER_PROVIDERS,
COMPILER_PROVIDERS,
provide(CompilerConfig, {
useFactory: (platformDirectives: any[], platformPipes: any[]) => {
return new CompilerConfig({ platformDirectives, platformPipes });
Expand Down Expand Up @@ -101,7 +114,7 @@ export function bootstrap(appComponentType: any,
// Http Setup
// Since HTTP_PROVIDERS can be added with customProviders above, this must come after
appProviders.push([
provide(XSRFStrategy, { useValue: new NSXSRFStrategy()}),
provide(XSRFStrategy, { useValue: new NSXSRFStrategy() }),
NSFileSystem,
provide(Http, {
useFactory: (backend, options, nsFileSystem) => {
Expand All @@ -110,7 +123,7 @@ export function bootstrap(appComponentType: any,
})
]);

var platform = getPlatform();
var platform = getPlatform();
if (!isPresent(platform)) {
platform = createPlatform(ReflectiveInjector.resolveAndCreate(platformProviders));
}
Expand All @@ -120,46 +133,89 @@ export function bootstrap(appComponentType: any,
return coreLoadAndBootstrap(appComponentType, appInjector);
}

function createNavigationEntry(params: BootstrapParams, resolve: (comp: ComponentRef<any>) => void, reject: (e: Error) => void, isReboot: boolean) {
const navEntry: NavigationEntry = {
create: (): Page => {
let page = new Page();
if (params.appOptions) {
page.actionBarHidden = params.appOptions.startPageActionBarHidden;
}

let onLoadedHandler = function (args) {
page.off('loaded', onLoadedHandler);
//profiling.stop('application-start');
rendererLog('Page loaded');

//profiling.start('ng-bootstrap');
rendererLog('BOOTSTRAPPING...');
bootstrap(params.appComponentType, params.customProviders).then((compRef) => {
//profiling.stop('ng-bootstrap');
rendererLog('ANGULAR BOOTSTRAP DONE.');
lastBootstrappedApp = new WeakRef(compRef);
resolve(compRef);
}, (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;
reject(err);
});
}

page.on('loaded', onLoadedHandler);

return page;
}
};

if (isReboot) {
navEntry.animated = false;
navEntry.clearHistory = true;
}

return navEntry;
}

export function nativeScriptBootstrap(appComponentType: any, customProviders?: ProviderArray, appOptions?: AppOptions): Promise<ComponentRef<any>> {
bootstrapCache = { appComponentType, customProviders, appOptions };

if (appOptions && appOptions.cssFile) {
application.cssFile = appOptions.cssFile;
}

return new Promise((resolve, reject) => {
application.start({
create: (): Page => {
let page = new Page();
if (appOptions) {
page.actionBarHidden = appOptions.startPageActionBarHidden;
}

let onLoadedHandler = function (args) {
page.off('loaded', onLoadedHandler);
//profiling.stop('application-start');
rendererLog('Page loaded');

//profiling.start('ng-bootstrap');
rendererLog('BOOTSTRAPPING...');
bootstrap(appComponentType, customProviders).then((appRef) => {
//profiling.stop('ng-bootstrap');
rendererLog('ANGULAR BOOTSTRAP DONE.');
resolve(appRef);
}, (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;
reject(err);
});
}

page.on('loaded', onLoadedHandler);

return page;
}
});
const navEntry = createNavigationEntry(bootstrapCache, resolve, reject, false);
application.start(navEntry);
})
}

// Patch livesync
const _baseLiveSync = global.__onLiveSync;
global.__onLiveSync = function () {
rendererLog("LiveSync Started")
if (bootstrapCache) {
onBeforeLivesync.next(lastBootstrappedApp ? lastBootstrappedApp.get() : null);

const frame = topmost();
const newEntry = createNavigationEntry(
bootstrapCache,
compRef => onAfterLivesync.next(compRef),
error => onAfterLivesync.error(error),
true);

if (frame) {
if (frame.currentPage && frame.currentPage.modal) {
frame.currentPage.modal.closeModal();
}
frame.navigate(newEntry);
}
}
else {
_baseLiveSync();
}
}


2 changes: 1 addition & 1 deletion nativescript-angular/hooks/before-livesync.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module.exports = function ($usbLiveSyncService) {
$usbLiveSyncService.forceExecuteFullSync = true;
$usbLiveSyncService.forceExecuteFullSync = false;
};
36 changes: 32 additions & 4 deletions ng-sample/app/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,16 @@
//profiling.start('application-start');

// this import should be first in order to load some required settings (like globals and reflect-metadata)
import { nativeScriptBootstrap } from "nativescript-angular/application";
import { Router } from "@angular/router";
import { nativeScriptBootstrap, onAfterLivesync, onBeforeLivesync } from "nativescript-angular/application";
import { NS_ROUTER_PROVIDERS as NS_ROUTER_PROVIDERS_DEPRECATED } from "nativescript-angular/router-deprecated";
import { NS_ROUTER_PROVIDERS } from "nativescript-angular/router";
import { HTTP_PROVIDERS } from "@angular/http";
import { rendererTraceCategory, routerTraceCategory, listViewTraceCategory } from "nativescript-angular/trace";

import trace = require("trace");
// trace.setCategories(rendererTraceCategory);
trace.setCategories(routerTraceCategory);
// trace.setCategories(routerTraceCategory);
// trace.setCategories(listViewTraceCategory);
trace.enable();

Expand All @@ -28,6 +29,7 @@ import {HttpTest} from "./examples/http/http-test";
import {ActionBarTest} from "./examples/action-bar/action-bar-test";
import {ModalTest} from "./examples/modal/modal-test";
import {PlatfromDirectivesTest} from "./examples/platform-directives/platform-directives-test";
import {LivesyncApp, LivesyncTestRouterProviders} from "./examples/livesync-test/livesync-test-app";

// router-deprecated
import {NavigationTest} from "./examples/router-deprecated/navigation-test";
Expand All @@ -39,13 +41,14 @@ import { RouterOutletAppComponent, RouterOutletRouterProviders} from "./examples
import { PageRouterOutletAppComponent, PageRouterOutletRouterProviders } from "./examples/router/page-router-outlet-test"
import { PageRouterOutletNestedAppComponent, PageRouterOutletNestedRouterProviders } from "./examples/router/page-router-outlet-nested-test"

//nativeScriptBootstrap(RendererTest);

nativeScriptBootstrap(RendererTest);
//nativeScriptBootstrap(TabViewTest);
//nativeScriptBootstrap(Benchmark);
// nativeScriptBootstrap(ListTest);
// nativeScriptBootstrap(ListTestAsync);
//nativeScriptBootstrap(ImageTest);
nativeScriptBootstrap(HttpTest, [HTTP_PROVIDERS]);
// nativeScriptBootstrap(HttpTest, [HTTP_PROVIDERS]);
//nativeScriptBootstrap(ActionBarTest, [NS_ROUTER_PROVIDERS_DEPRECATED], { startPageActionBarHidden: false });
//nativeScriptBootstrap(ActionBarTest, [NS_ROUTER_PROVIDERS_DEPRECATED]);
//nativeScriptBootstrap(ModalTest);
Expand All @@ -60,3 +63,28 @@ nativeScriptBootstrap(HttpTest, [HTTP_PROVIDERS]);
// nativeScriptBootstrap(NavigationTest, [NS_ROUTER_PROVIDERS_DEPRECATED]);
// nativeScriptBootstrap(RouterOutletTest, [NS_ROUTER_PROVIDERS_DEPRECATED]);
// nativeScriptBootstrap(LoginTest, [NS_ROUTER_PROVIDERS_DEPRECATED]);


// Livesync test
// var cahcedUrl: string;
// onBeforeLivesync.subscribe((compRef) => {
// console.log("------- onBeforeLivesync");
// if (compRef) {
// const router = <Router>compRef.injector.get(Router);
// cahcedUrl = router.url;
// console.log("------- Caching URL: " + cahcedUrl);
// }
// });

// onAfterLivesync.subscribe((compRef) => {
// console.log("------- onAfterLivesync cachedUrl:");
// const router = <Router>compRef.injector.get(Router);
// router.events.subscribe(e => console.log(e.toString()));
// if (router && cahcedUrl) {
// setTimeout(() => { router.navigateByUrl(cahcedUrl); }, 0);
// }
// });

// nativeScriptBootstrap(LivesyncApp, [LivesyncTestRouterProviders]);


14 changes: 14 additions & 0 deletions ng-sample/app/examples/livesync-test/first/first.component.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
.title {
font-size: 30;
margin: 16;
color: darkblue;
}

button {
horizontal-align: center;
margin: 10;
}

stack-layout {
background-color: lightgreen;
}
12 changes: 12 additions & 0 deletions ng-sample/app/examples/livesync-test/first/first.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { Component } from "@angular/core";
import { ROUTER_DIRECTIVES } from '@angular/router';
import { NS_ROUTER_DIRECTIVES} from "nativescript-angular/router"

@Component({
selector: "first",
directives: [ROUTER_DIRECTIVES, NS_ROUTER_DIRECTIVES],
styleUrls: ["examples/livesync-test/first/first.component.css"],
templateUrl: "examples/livesync-test/first/first.component.xml"
})
export class FirstComponent {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<StackLayout>
<Label text="First Page" class="title"></Label>
<Button text="Go to second" nsRouterLink="second"></Button>
</StackLayout>
22 changes: 22 additions & 0 deletions ng-sample/app/examples/livesync-test/livesync-test-app.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { Component } from "@angular/core";
import { RouterConfig } from '@angular/router';
import { NS_ROUTER_DIRECTIVES, nsProvideRouter} from "nativescript-angular/router"

import {FirstComponent} from "./first/first.component";
import {SecondComponent} from "./second/second.component";

@Component({
selector: 'livesync-app-test',
directives: [NS_ROUTER_DIRECTIVES],
template: `<page-router-outlet></page-router-outlet>`
})
export class LivesyncApp { }

const routes: RouterConfig = [
{ path: "", component: FirstComponent },
{ path: "second", component: SecondComponent },
];

export const LivesyncTestRouterProviders = [
nsProvideRouter(routes, { enableTracing: false })
];
14 changes: 14 additions & 0 deletions ng-sample/app/examples/livesync-test/second/second.component.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
.title {
font-size: 30;
margin: 16;
color: darkgreen;
}

button {
horizontal-align: center;
margin: 10;
}

stack-layout {
background-color: lightblue;
}
12 changes: 12 additions & 0 deletions ng-sample/app/examples/livesync-test/second/second.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { Component } from "@angular/core";
import { ROUTER_DIRECTIVES } from '@angular/router';
import { NS_ROUTER_DIRECTIVES} from "nativescript-angular/router"

@Component({
selector: "second",
directives: [ROUTER_DIRECTIVES, NS_ROUTER_DIRECTIVES],
styleUrls: ["examples/livesync-test/second/second.component.css"],
templateUrl: "examples/livesync-test/second/second.component.xml"
})
export class SecondComponent {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<StackLayout>
<Label text="Second Page" class="title"></Label>
<Button text="Go to first" nsRouterLink=""></Button>
</StackLayout>