Skip to content

feat: Angular 4.2 support #842

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 28 commits into from
Jul 31, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
c747854
fix(page-router-outlet): upgrade to be compliant with ng 4.2
sis0k0 Jun 13, 2017
415c938
chore: exclude hooks from source control
sis0k0 Jun 27, 2017
c64a80b
style: typo in variable name
sis0k0 Jul 6, 2017
6d76d64
style: code formatting
sis0k0 Jul 6, 2017
6bde2e4
refactor: add trace for animations
sis0k0 Jul 6, 2017
3072da5
feat: implement simple animation driver
sis0k0 Jul 6, 2017
6a2c160
refactor: use eachDescendant instead of eachChild for containsElement
sis0k0 Jul 6, 2017
8765313
refactor: implement NSTransitionEngine and NativeScriptAnimationEngine
sis0k0 Jul 6, 2017
b8034d8
refactor: use NativeScriptAnimationEngine in Animations module
sis0k0 Jul 6, 2017
4548af3
refactor: embed non-exported code from angular
sis0k0 Jul 7, 2017
7104031
refactor(ng-sample): animation examples style
sis0k0 Jul 7, 2017
6cb2bac
chore: update deps
sis0k0 Jul 7, 2017
bf370af
style: remove no-shadowed-variable rule
sis0k0 Jul 7, 2017
2f61dac
refactor: always set camelCase props for animations
sis0k0 Jul 8, 2017
ceeb869
refactor: add multi-states animation example
sis0k0 Jul 8, 2017
b54a8a0
refactor: enable * states
sis0k0 Jul 8, 2017
40f5e15
refactor: update private imports from ng animations
sis0k0 Jul 8, 2017
68f6894
refactor: move no-unused-variable from tsconfig to tslint
sis0k0 Jul 8, 2017
cfc1371
refactor: update states animations example
sis0k0 Jul 8, 2017
4dc6544
fix(animations): override transitionEngine element removal
sis0k0 Jul 14, 2017
8071257
lint: remove unused variables
sis0k0 Jul 14, 2017
d89f8d8
fix(animations): ignore setting '*' property for styles
sis0k0 Jul 14, 2017
6b6208b
feat(animations): implement query selector for ani driver
sis0k0 Jul 20, 2017
f646bd4
fix(animations): skip `InvisibleNode`s when querying for elements
sis0k0 Jul 20, 2017
9bebc2a
fix(animations): implement containsElement method for driver
sis0k0 Jul 21, 2017
b3cd887
fix(animations): implement finish method for player
sis0k0 Jul 22, 2017
e308645
refactor: separate NativeScriptCommonModule from NativeScriptModule
sis0k0 Jul 22, 2017
8488874
style(tslint): no-shadowed-variable enabled
Jul 26, 2017
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
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,14 @@ tests/test-output.txt
tests/platforms
tests/lib
tests/node_modules
tests/hooks

ng-sample/app/**/*.js
ng-sample/app/global.d.ts
ng-sample/platforms
ng-sample/lib
ng-sample/node_modules
ng-sample/hooks
ng-sample/app/nativescript-angular

startup-test/platforms
Expand All @@ -52,4 +54,4 @@ startup-test/node_modules
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
!.vscode/extensions.json
22 changes: 14 additions & 8 deletions nativescript-angular/animations.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
import { NgModule, Injectable, NgZone, Provider, RendererFactory2 } from "@angular/core";

import { AnimationBuilder } from "@angular/animations";

import {
AnimationDriver,
ɵAnimationEngine as AnimationEngine,
ɵAnimationStyleNormalizer as AnimationStyleNormalizer,
ɵWebAnimationsStyleNormalizer as WebAnimationsStyleNormalizer
ɵWebAnimationsStyleNormalizer as WebAnimationsStyleNormalizer,
} from "@angular/animations/browser";

import { ɵAnimationRendererFactory as AnimationRendererFactory } from "@angular/platform-browser/animations";
import {
ɵAnimationRendererFactory as AnimationRendererFactory,
ɵBrowserAnimationBuilder as BrowserAnimationBuilder,
} from "@angular/platform-browser/animations";

import { NativeScriptAnimationEngine } from "./animations/animation-engine";
import { NativeScriptAnimationDriver } from "./animations/animation-driver";
Expand All @@ -26,21 +30,23 @@ export function instantiateSupportedAnimationDriver() {
}

export function instantiateRendererFactory(
renderer: NativeScriptRendererFactory, engine: AnimationEngine, zone: NgZone) {
renderer: NativeScriptRendererFactory, engine: NativeScriptAnimationEngine, zone: NgZone) {
return new AnimationRendererFactory(renderer, engine, zone);
}

export function instanciateDefaultStyleNormalizer() {
export function instantiateDefaultStyleNormalizer() {
return new WebAnimationsStyleNormalizer();
}

export const NATIVESCRIPT_ANIMATIONS_PROVIDERS: Provider[] = [
{provide: AnimationBuilder, useClass: BrowserAnimationBuilder},
{provide: AnimationDriver, useFactory: instantiateSupportedAnimationDriver},
{provide: AnimationStyleNormalizer, useFactory: instanciateDefaultStyleNormalizer},
{provide: AnimationEngine, useClass: InjectableAnimationEngine}, {
{provide: AnimationStyleNormalizer, useFactory: instantiateDefaultStyleNormalizer},
{provide: NativeScriptAnimationEngine, useClass: InjectableAnimationEngine},
{
provide: RendererFactory2,
useFactory: instantiateRendererFactory,
deps: [NativeScriptRendererFactory, AnimationEngine, NgZone]
deps: [NativeScriptRendererFactory, NativeScriptAnimationEngine, NgZone]
}
];

Expand Down
180 changes: 169 additions & 11 deletions nativescript-angular/animations/animation-driver.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,117 @@
import { AnimationPlayer } from "@angular/animations";
import { AnimationDriver } from "@angular/animations/browser";
import { eachDescendant } from "tns-core-modules/ui/core/view";

import { NgView } from "../element-registry";
import { NativeScriptAnimationPlayer } from "./animation-player";
import { Keyframe } from "./utils";
import {
Keyframe,
dashCaseToCamelCase,
} from "./utils";
import { NgView, InvisibleNode } from "../element-registry";
import { animationsLog as traceLog } from "../trace";

export abstract class AnimationDriver {
abstract animate(
element: any,
keyframes: Keyframe[],
duration: number,
delay: number,
easing: string
): AnimationPlayer;
import { createSelector, SelectorCore } from "tns-core-modules/ui/styling/css-selector";

interface ViewMatchResult {
found: boolean;
}

interface ViewMatchParams {
originalView: NgView;
}

interface QueryParams {
selector: Selector;
multi: boolean;
}

interface QueryResult {
matches: NgView[];
}

class Selector {
private nsSelectors: SelectorCore[];
private classSelectors: string[];

constructor(rawSelector: string) {
this.parse(rawSelector);
}

match(element: NgView): boolean {
return this.nsSelectorMatch(element) || this.classSelectorsMatch(element);
}

private parse(rawSelector: string) {
const selectors = rawSelector.split(",").map(s => s.trim());

this.nsSelectors = selectors.map(createSelector);
this.classSelectors = selectors
.filter(s => s.startsWith("."))
.map(s => s.substring(1));
}

private nsSelectorMatch(element: NgView) {
return this.nsSelectors.some(s => s.match(element));
}

private classSelectorsMatch(element: NgView) {
return this.classSelectors.some(s => this.hasClass(element, s));
}

// we're using that instead of match for classes
// that are dynamically added by the animation engine
// such as .ng-trigger, that's added for every :enter view
private hasClass(element: NgView, cls: string) {
return element && element["$$classes"] && element["$$classes"][cls];
}
}

export class NativeScriptAnimationDriver implements AnimationDriver {
matchesElement(element: NgView, rawSelector: string): boolean {
traceLog(
`NativeScriptAnimationDriver.matchesElement ` +
`element: ${element}, selector: ${rawSelector}`
);

const selector = this.makeSelector(rawSelector);
return selector.match(element);
}


containsElement(elm1: NgView, elm2: NgView): boolean {
traceLog(
`NativeScriptAnimationDriver.containsElement ` +
`element1: ${elm1}, element2: ${elm2}`
);

const params: ViewMatchParams = { originalView: elm2 };
const result: ViewMatchResult = this.visitDescendants(elm1, viewMatches, params);

return result.found;
}

query(element: NgView, rawSelector: string, multi: boolean): NgView[] {
traceLog(
`NativeScriptAnimationDriver.query ` +
`element: ${element}, selector: ${rawSelector} ` +
`multi: ${multi}`
);

const selector = this.makeSelector(rawSelector);
const params: QueryParams = { selector, multi };
const result: QueryResult = this.visitDescendants(element, queryDescendants, params);

return result.matches || [];
}

computeStyle(element: NgView, prop: string): string {
return element.style[`css-${prop}`];
traceLog(
`NativeScriptAnimationDriver.computeStyle ` +
`element: ${element}, prop: ${prop}`
);

const camelCaseProp = dashCaseToCamelCase(prop);
return element.style[camelCaseProp];
}

animate(
Expand All @@ -26,7 +121,70 @@ export class NativeScriptAnimationDriver implements AnimationDriver {
delay: number,
easing: string
): AnimationPlayer {
traceLog(
`NativeScriptAnimationDriver.animate ` +
`element: ${element}, keyframes: ${keyframes} ` +
`duration: ${duration}, delay: ${delay} ` +
`easing: ${easing}`
);

return new NativeScriptAnimationPlayer(
element, keyframes, duration, delay, easing);
}

private makeSelector(rawSelector: string): Selector {
return new Selector(rawSelector);
}

private visitDescendants(
element: NgView,
cb: (child: NgView, result: any, params: any) => boolean,
cbParams: any): any {

const result = {};
// fill the result obj with the result from the callback function
eachDescendant(element, (child: NgView) => cb(child, result, cbParams));

return result;
}
}

function viewMatches(
element: NgView,
result: ViewMatchResult,
params: ViewMatchParams
): boolean {

if (element === params.originalView) {
result.found = true;
}

return !result.found;
}

function queryDescendants(
element: NgView,
result: QueryResult,
params: QueryParams
): boolean {

if (!result.matches) {
result.matches = [];
}

const { selector, multi } = params;

// skip comment and text nodes
// because they are not actual Views
// and cannot be animated
if (element instanceof InvisibleNode) {
return true;
}

if (selector.match(element)) {
result.matches.push(element);
return multi;
}

return true;
}
Loading