From 9fb3833b7278c982d148d0019fce60daaeeb07af Mon Sep 17 00:00:00 2001 From: vakrilov Date: Fri, 25 Mar 2016 18:35:23 +0200 Subject: [PATCH 1/4] Platform filter directives --- ng-sample/app/app.ts | 6 ++++-- .../platform-directives-test.ts | 19 +++++++++++++++++++ .../directives/ns-directives.ts | 5 ++++- .../directives/platform-filters.ts | 18 ++++++++++++++++++ 4 files changed, 45 insertions(+), 3 deletions(-) create mode 100644 ng-sample/app/examples/platform-directives/platform-directives-test.ts create mode 100644 src/nativescript-angular/directives/platform-filters.ts diff --git a/ng-sample/app/app.ts b/ng-sample/app/app.ts index fe26d72d3..3e094b1ca 100644 --- a/ng-sample/app/app.ts +++ b/ng-sample/app/app.ts @@ -24,8 +24,9 @@ import {ImageTest} from "./examples/image/image-test"; import {NavigationTest} from "./examples/navigation/navigation-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"; -nativeScriptBootstrap(RendererTest); +// nativeScriptBootstrap(RendererTest); //nativeScriptBootstrap(Benchmark); //nativeScriptBootstrap(ListTest); //nativeScriptBootstrap(ListTestAsync); @@ -34,5 +35,6 @@ nativeScriptBootstrap(RendererTest); //nativeScriptBootstrap(ListTestAsync); //nativeScriptBootstrap(ImageTest); //nativeScriptBootstrap(NavigationTest, [NS_ROUTER_PROVIDERS]); -//nativeScriptBootstrap(ActionBarTest, [NS_ROUTER_PROVIDERS], { startPageActionBarHidden: false }); +// nativeScriptBootstrap(ActionBarTest, [NS_ROUTER_PROVIDERS], { startPageActionBarHidden: false }); // nativeScriptBootstrap(ModalTest); +nativeScriptBootstrap(PlatfromDirectivesTest); diff --git a/ng-sample/app/examples/platform-directives/platform-directives-test.ts b/ng-sample/app/examples/platform-directives/platform-directives-test.ts new file mode 100644 index 000000000..a7c5dfe5b --- /dev/null +++ b/ng-sample/app/examples/platform-directives/platform-directives-test.ts @@ -0,0 +1,19 @@ +import {Component, View} from 'angular2/core'; +import {RouteConfig} from 'angular2/router'; +import { Page} from "ui/page"; +import {NS_ROUTER_DIRECTIVES, NS_ROUTER_PROVIDERS} from "../../nativescript-angular/router/ns-router"; +import {NS_DIRECTIVES} from "../../nativescript-angular/directives/ns-directives"; + +@Component({ + selector: 'action-bar-test', + template: ` + + + + + ` +}) +export class PlatfromDirectivesTest { +} + + diff --git a/src/nativescript-angular/directives/ns-directives.ts b/src/nativescript-angular/directives/ns-directives.ts index 670d847be..70f18cb41 100644 --- a/src/nativescript-angular/directives/ns-directives.ts +++ b/src/nativescript-angular/directives/ns-directives.ts @@ -8,6 +8,7 @@ import {NumberValueAccessor} from '../value-accessors/number-value-accessor'; import {SelectedIndexValueAccessor} from '../value-accessors/selectedIndex-value-accessor'; import {TabViewDirective, TabViewItemDirective} from './tab-view'; import {ActionBarComponent, ActionBarScope, ActionItemDirective, NavigationButtonDirective} from './action-bar'; +import {AndroidFilterComponent, IosFilterComponent} from './platform-filters'; export const NS_DIRECTIVES: Type[] = [ ListViewComponent, @@ -22,5 +23,7 @@ export const NS_DIRECTIVES: Type[] = [ ActionBarComponent, ActionBarScope, ActionItemDirective, - NavigationButtonDirective + NavigationButtonDirective, + AndroidFilterComponent, + IosFilterComponent ]; diff --git a/src/nativescript-angular/directives/platform-filters.ts b/src/nativescript-angular/directives/platform-filters.ts new file mode 100644 index 000000000..5436be441 --- /dev/null +++ b/src/nativescript-angular/directives/platform-filters.ts @@ -0,0 +1,18 @@ +import {Component} from 'angular2/core'; +import {device, platformNames} from "platform"; + +@Component({ + selector: "android", + template: ``, +}) +export class AndroidFilterComponent { + public show: boolean = device.os === platformNames.android; +} + +@Component({ + selector: "ios", + template: ``, +}) +export class IosFilterComponent { + public show: boolean = device.os === platformNames.ios; +} \ No newline at end of file From 510439a0166a087f18ac874e489b9ad666adbea6 Mon Sep 17 00:00:00 2001 From: vakrilov Date: Fri, 25 Mar 2016 19:01:02 +0200 Subject: [PATCH 2/4] Platfrom specific attributes --- .../platform-directives-test.ts | 13 ++++---- src/nativescript-angular/view-util.ts | 31 +++++++++++++++++++ 2 files changed, 37 insertions(+), 7 deletions(-) diff --git a/ng-sample/app/examples/platform-directives/platform-directives-test.ts b/ng-sample/app/examples/platform-directives/platform-directives-test.ts index a7c5dfe5b..3ed8f1156 100644 --- a/ng-sample/app/examples/platform-directives/platform-directives-test.ts +++ b/ng-sample/app/examples/platform-directives/platform-directives-test.ts @@ -1,15 +1,14 @@ -import {Component, View} from 'angular2/core'; -import {RouteConfig} from 'angular2/router'; -import { Page} from "ui/page"; -import {NS_ROUTER_DIRECTIVES, NS_ROUTER_PROVIDERS} from "../../nativescript-angular/router/ns-router"; -import {NS_DIRECTIVES} from "../../nativescript-angular/directives/ns-directives"; +import {Component} from 'angular2/core'; @Component({ selector: 'action-bar-test', template: ` - - + + + ` }) diff --git a/src/nativescript-angular/view-util.ts b/src/nativescript-angular/view-util.ts index d9550903e..2c8b3daf7 100644 --- a/src/nativescript-angular/view-util.ts +++ b/src/nativescript-angular/view-util.ts @@ -7,7 +7,12 @@ import {ViewClass, getViewClass, getViewMeta, isKnownView, ViewExtensions, NgVie import {getSpecialPropertySetter} from "ui/builder/special-properties"; import { ActionBar, ActionItem, NavigationButton } from "ui/action-bar"; import trace = require("trace"); +import {device, platformNames} from "platform"; +const isIos: boolean = device.os === platformNames.ios; +const isAndroid: boolean = device.os === platformNames.android; +const IOS_PREFX: string = "@ios:"; +const ANDROID_PREFX: string = "@android:"; export const rendererTraceCategory = "ns-renderer"; export function traceLog(msg) { @@ -142,7 +147,33 @@ function isXMLAttribute(name: string): boolean { } } +function platformFilter(attribute: string): string { + var lowered = attribute.toLowerCase(); + if (lowered.indexOf(IOS_PREFX) === 0) { + if (isIos) { + return attribute.substr(IOS_PREFX.length); + } else { + return null; + } + } + + if (lowered.indexOf(ANDROID_PREFX) === 0) { + if (isAndroid) { + return attribute.substr(ANDROID_PREFX.length); + } else { + return null; + } + } + + return attribute; +} + export function setProperty(view: NgView, attributeName: string, value: any): void { + attributeName = platformFilter(attributeName); + if (!attributeName) { + return; + } + if (attributeName.indexOf(".") !== -1) { // Handle nested properties const properties = attributeName.split("."); From 589013fd644afda73ae2b3377538af57ce5cb751 Mon Sep 17 00:00:00 2001 From: vakrilov Date: Tue, 29 Mar 2016 13:59:01 +0300 Subject: [PATCH 3/4] Dependency to modules updated to 2.0.0-angular-2 --- ng-sample/package.json | 2 +- package.json | 2 +- tests/package.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ng-sample/package.json b/ng-sample/package.json index 0cc2915a2..eea477e00 100644 --- a/ng-sample/package.json +++ b/ng-sample/package.json @@ -23,7 +23,7 @@ }, "homepage": "https://github.com/NativeScript/template-hello-world", "dependencies": { - "tns-core-modules": "^2.0.0-angular-1", + "tns-core-modules": "^2.0.0-angular-2", "nativescript-intl": "^0.0.2", "angular2": "2.0.0-beta.9", "parse5": "1.4.2", diff --git a/package.json b/package.json index 03573b020..22d0d4ebd 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ }, "scripts": {}, "dependencies": { - "tns-core-modules": "^2.0.0-angular-1", + "tns-core-modules": "^2.0.0-angular-2", "nativescript-intl": "^0.0.2", "angular2": "2.0.0-beta.9", "es6-shim": "^0.33.3", diff --git a/tests/package.json b/tests/package.json index c3666271f..2d2c54354 100644 --- a/tests/package.json +++ b/tests/package.json @@ -30,7 +30,7 @@ }, "homepage": "http://nativescript.org", "dependencies": { - "tns-core-modules": "2.0.0-angular-1", + "tns-core-modules": "2.0.0-angular-2", "nativescript-intl": "^0.0.2", "angular2": "2.0.0-beta.9", "nativescript-unit-test-runner": "^0.3.3", From 391ffbc92b71c21d096cb93f6aaefbb997784c35 Mon Sep 17 00:00:00 2001 From: vakrilov Date: Tue, 29 Mar 2016 14:02:05 +0300 Subject: [PATCH 4/4] Platform-componenets tests. --- ng-sample/app/app.ts | 4 +- src/nativescript-angular/application.ts | 3 +- .../directives/platform-filters.ts | 15 +- .../platform-providers.ts | 7 +- src/nativescript-angular/renderer.ts | 121 ++--- src/nativescript-angular/view-util.ts | 421 +++++++++--------- tests/app/tests/platform-filter-components.ts | 95 ++++ tests/app/tests/property-sets.ts | 63 ++- tests/app/tests/test-app.ts | 4 +- tests/app/tests/test-utils.ts | 15 + .../nativescript-unit-test-runner.js | 2 +- 11 files changed, 463 insertions(+), 287 deletions(-) create mode 100644 tests/app/tests/platform-filter-components.ts diff --git a/ng-sample/app/app.ts b/ng-sample/app/app.ts index 3e094b1ca..40131f25a 100644 --- a/ng-sample/app/app.ts +++ b/ng-sample/app/app.ts @@ -26,7 +26,7 @@ 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"; -// nativeScriptBootstrap(RendererTest); +nativeScriptBootstrap(RendererTest); //nativeScriptBootstrap(Benchmark); //nativeScriptBootstrap(ListTest); //nativeScriptBootstrap(ListTestAsync); @@ -37,4 +37,4 @@ import {PlatfromDirectivesTest} from "./examples/platform-directives/platform-di //nativeScriptBootstrap(NavigationTest, [NS_ROUTER_PROVIDERS]); // nativeScriptBootstrap(ActionBarTest, [NS_ROUTER_PROVIDERS], { startPageActionBarHidden: false }); // nativeScriptBootstrap(ModalTest); -nativeScriptBootstrap(PlatfromDirectivesTest); +// nativeScriptBootstrap(PlatfromDirectivesTest); diff --git a/src/nativescript-angular/application.ts b/src/nativescript-angular/application.ts index 38bdb4391..e59cfc419 100644 --- a/src/nativescript-angular/application.ts +++ b/src/nativescript-angular/application.ts @@ -39,7 +39,7 @@ import application = require('application'); export type ProviderArray = Array; -import {defaultPageProvider} from "./platform-providers"; +import {defaultPageProvider, defaultDeviceProvider} from "./platform-providers"; import * as nativescriptIntl from "nativescript-intl"; global.Intl = nativescriptIntl; @@ -68,6 +68,7 @@ export function bootstrap(appComponentType: any, provide(ExceptionHandler, {useFactory: () => new ExceptionHandler(DOM, true), deps: []}), defaultPageProvider, + defaultDeviceProvider, NativeScriptRootRenderer, provide(RootRenderer, {useClass: NativeScriptRootRenderer}), NativeScriptRenderer, diff --git a/src/nativescript-angular/directives/platform-filters.ts b/src/nativescript-angular/directives/platform-filters.ts index 5436be441..8e6dd8e56 100644 --- a/src/nativescript-angular/directives/platform-filters.ts +++ b/src/nativescript-angular/directives/platform-filters.ts @@ -1,12 +1,16 @@ -import {Component} from 'angular2/core'; -import {device, platformNames} from "platform"; +import {Component, Inject} from 'angular2/core'; +import {Device, platformNames} from "platform"; +import {DEVICE} from "../platform-providers"; @Component({ selector: "android", template: ``, }) export class AndroidFilterComponent { - public show: boolean = device.os === platformNames.android; + public show: boolean; + constructor( @Inject(DEVICE) device: Device) { + this.show = (device.os === platformNames.android); + } } @Component({ @@ -14,5 +18,8 @@ export class AndroidFilterComponent { template: ``, }) export class IosFilterComponent { - public show: boolean = device.os === platformNames.ios; + public show: boolean; + constructor( @Inject(DEVICE) device: Device) { + this.show = (device.os === platformNames.ios); + } } \ No newline at end of file diff --git a/src/nativescript-angular/platform-providers.ts b/src/nativescript-angular/platform-providers.ts index 3c3645cf2..a81f93d3d 100644 --- a/src/nativescript-angular/platform-providers.ts +++ b/src/nativescript-angular/platform-providers.ts @@ -1,10 +1,12 @@ import {topmost} from 'ui/frame'; import {Page} from 'ui/page'; import {provide, Provider, OpaqueToken} from 'angular2/src/core/di'; +import {Device, ScreenMetrics, device, screen} from "platform"; export const APP_ROOT_VIEW = new OpaqueToken('App Root View'); +export const DEVICE = new OpaqueToken('platfrom device'); -export const defaultPageProvider = provide(Page, {useFactory: getDefaultPage}); +export const defaultPageProvider = provide(Page, { useFactory: getDefaultPage }); export function getDefaultPage(): Page { const frame = topmost(); @@ -14,3 +16,6 @@ export function getDefaultPage(): Page { return null; } } + +export const defaultDeviceProvider = provide(DEVICE, { useValue: device }); + diff --git a/src/nativescript-angular/renderer.ts b/src/nativescript-angular/renderer.ts index 081fb4c91..a787b16b2 100644 --- a/src/nativescript-angular/renderer.ts +++ b/src/nativescript-angular/renderer.ts @@ -5,7 +5,7 @@ import { RenderComponentType, RenderDebugInfo } from 'angular2/src/core/render/api'; -import {APP_ROOT_VIEW} from "./platform-providers"; +import {APP_ROOT_VIEW, DEVICE} from "./platform-providers"; import {isBlank} from 'angular2/src/facade/lang'; import {DOM} from 'angular2/src/platform/dom/dom_adapter'; import {COMPONENT_VARIABLE, CONTENT_ATTR} from 'angular2/src/platform/dom/dom_renderer'; @@ -13,16 +13,20 @@ import {View} from "ui/core/view"; import * as application from "application"; import {topmost} from 'ui/frame'; import {Page} from 'ui/page'; -import * as util from "./view-util"; +import {traceLog, ViewUtil, NgView} from "./view-util"; import {escapeRegexSymbols} from "utils/utils"; +import { Device } from "platform"; export { rendererTraceCategory } from "./view-util"; @Injectable() export class NativeScriptRootRenderer implements RootRenderer { private _rootView: View = null; - constructor(@Optional() @Inject(APP_ROOT_VIEW) rootView: View) { + private _viewUtil: ViewUtil; + + constructor( @Optional() @Inject(APP_ROOT_VIEW) rootView: View, @Inject(DEVICE) device: Device) { this._rootView = rootView; + this._viewUtil = new ViewUtil(device); } private _registeredComponents: Map = new Map(); @@ -38,6 +42,10 @@ export class NativeScriptRootRenderer implements RootRenderer { return this.rootView.page; } + public get viewUtil(): ViewUtil { + return this._viewUtil; + } + renderComponent(componentProto: RenderComponentType): Renderer { var renderer = this._registeredComponents.get(componentProto.id); if (isBlank(renderer)) { @@ -53,19 +61,24 @@ export class NativeScriptRenderer extends Renderer { private componentProtoId: string; private hasComponentStyles: boolean; private rootRenderer: NativeScriptRootRenderer; + + private get viewUtil(): ViewUtil { + return this.rootRenderer.viewUtil; + } + constructor(private _rootRenderer: NativeScriptRootRenderer, private componentProto: RenderComponentType) { super(); this.rootRenderer = _rootRenderer; let page = this.rootRenderer.page; let stylesLength = componentProto.styles.length; this.componentProtoId = componentProto.id; - for(let i = 0; i < stylesLength; i++) { + for (let i = 0; i < stylesLength; i++) { this.hasComponentStyles = true; let cssString = componentProto.styles[i] + ""; const realCSS = this.replaceNgAttribute(cssString, this.componentProtoId); application.addCss(realCSS); } - util.traceLog('NativeScriptRenderer created'); + traceLog('NativeScriptRenderer created'); } private attrReplacer = new RegExp(escapeRegexSymbols(CONTENT_ATTR), "g"); @@ -73,120 +86,120 @@ export class NativeScriptRenderer extends Renderer { private replaceNgAttribute(input: string, componentId: string): string { return input.replace(this.attrReplacer, - "_ng_content_" + componentId.replace(this.attrSanitizer, "_")); + "_ng_content_" + componentId.replace(this.attrSanitizer, "_")); } renderComponent(componentProto: RenderComponentType): Renderer { return this._rootRenderer.renderComponent(componentProto); } - selectRootElement(selector: string): util.NgView { - util.traceLog('selectRootElement: ' + selector); - const rootView = this.rootRenderer.rootView; + selectRootElement(selector: string): NgView { + traceLog('selectRootElement: ' + selector); + const rootView = this.rootRenderer.rootView; rootView.nodeName = 'ROOT'; return rootView; } - createViewRoot(hostElement: util.NgView): util.NgView { - util.traceLog('CREATE VIEW ROOT: ' + hostElement.nodeName); + createViewRoot(hostElement: NgView): NgView { + traceLog('CREATE VIEW ROOT: ' + hostElement.nodeName); return hostElement; } - projectNodes(parentElement: util.NgView, nodes: util.NgView[]): void { - util.traceLog('NativeScriptRenderer.projectNodes'); + projectNodes(parentElement: NgView, nodes: NgView[]): void { + traceLog('NativeScriptRenderer.projectNodes'); nodes.forEach((node) => { - util.insertChild(parentElement, node); + this.viewUtil.insertChild(parentElement, node); }); } - attachViewAfter(anchorNode: util.NgView, viewRootNodes: util.NgView[]) { - util.traceLog('NativeScriptRenderer.attachViewAfter: ' + anchorNode.nodeName + ' ' + anchorNode); - const parent = (anchorNode.parent || anchorNode.templateParent); - const insertPosition = util.getChildIndex(parent, anchorNode); + attachViewAfter(anchorNode: NgView, viewRootNodes: NgView[]) { + traceLog('NativeScriptRenderer.attachViewAfter: ' + anchorNode.nodeName + ' ' + anchorNode); + const parent = (anchorNode.parent || anchorNode.templateParent); + const insertPosition = this.viewUtil.getChildIndex(parent, anchorNode); viewRootNodes.forEach((node, index) => { const childIndex = insertPosition + index + 1; - util.insertChild(parent, node, childIndex); + this.viewUtil.insertChild(parent, node, childIndex); this.animateNodeEnter(node); }); } - detachView(viewRootNodes: util.NgView[]) { - util.traceLog('NativeScriptRenderer.detachView'); + detachView(viewRootNodes: NgView[]) { + traceLog('NativeScriptRenderer.detachView'); for (var i = 0; i < viewRootNodes.length; i++) { var node = viewRootNodes[i]; - util.removeChild(node.parent, node); + this.viewUtil.removeChild(node.parent, node); this.animateNodeLeave(node); } } - animateNodeEnter(node: util.NgView) { + animateNodeEnter(node: NgView) { } - animateNodeLeave(node: util.NgView) { + animateNodeLeave(node: NgView) { } - public destroyView(hostElement: util.NgView, viewAllNodes: util.NgView[]) { - util.traceLog("NativeScriptRenderer.destroyView"); + public destroyView(hostElement: NgView, viewAllNodes: NgView[]) { + traceLog("NativeScriptRenderer.destroyView"); // Seems to be called on component dispose only (router outlet) //TODO: handle this when we resolve routing and navigation. } - setElementProperty(renderElement: util.NgView, propertyName: string, propertyValue: any) { - util.traceLog("NativeScriptRenderer.setElementProperty " + renderElement + ': ' + propertyName + " = " + propertyValue); - util.setProperty(renderElement, propertyName, propertyValue); + setElementProperty(renderElement: NgView, propertyName: string, propertyValue: any) { + traceLog("NativeScriptRenderer.setElementProperty " + renderElement + ': ' + propertyName + " = " + propertyValue); + this.viewUtil.setProperty(renderElement, propertyName, propertyValue); } - setElementAttribute(renderElement: util.NgView, attributeName: string, attributeValue: string) { - util.traceLog("NativeScriptRenderer.setElementAttribute " + renderElement + ': ' + attributeName + " = " + attributeValue); + setElementAttribute(renderElement: NgView, attributeName: string, attributeValue: string) { + traceLog("NativeScriptRenderer.setElementAttribute " + renderElement + ': ' + attributeName + " = " + attributeValue); return this.setElementProperty(renderElement, attributeName, attributeValue); } - setElementClass(renderElement: util.NgView, className: string, isAdd: boolean): void { - util.traceLog("NativeScriptRenderer.setElementClass " + className + " - " + isAdd); + setElementClass(renderElement: NgView, className: string, isAdd: boolean): void { + traceLog("NativeScriptRenderer.setElementClass " + className + " - " + isAdd); if (isAdd) { - util.addClass(renderElement, className); + this.viewUtil.addClass(renderElement, className); } else { - util.removeClass(renderElement, className); + this.viewUtil.removeClass(renderElement, className); } } - setElementStyle(renderElement: util.NgView, styleName: string, styleValue: string): void { - util.setStyleProperty(renderElement, styleName, styleValue); + setElementStyle(renderElement: NgView, styleName: string, styleValue: string): void { + this.viewUtil.setStyleProperty(renderElement, styleName, styleValue); } /** * Used only in debug mode to serialize property changes to comment nodes, * such as