From 42a1491e6e089200414f7dc13718e7a9380945c7 Mon Sep 17 00:00:00 2001 From: Vasil Chimev Date: Thu, 4 Oct 2018 19:20:13 +0300 Subject: [PATCH 01/28] feat(HMR): apply changes in application styles at runtime Expose `HmrContext` interface. Apply changes in `app.css` instantly. Avoid navigation on livesync when changes in `app.css` have been made. Apply changes in `app.css` on back navigation. --- .../application/application-common.ts | 6 ++-- .../application/application.android.ts | 4 +-- .../application/application.ios.ts | 28 +++++++++++----- tns-core-modules/module.d.ts | 25 +++++++++++++-- tns-core-modules/ui/frame/frame.android.ts | 32 +++++++++++++------ tns-core-modules/ui/page/page-common.ts | 12 ++++--- tns-core-modules/ui/styling/style-scope.d.ts | 8 +++++ tns-core-modules/ui/styling/style-scope.ts | 27 +++++++++++++--- tsconfig.shared.json | 2 +- 9 files changed, 110 insertions(+), 34 deletions(-) diff --git a/tns-core-modules/application/application-common.ts b/tns-core-modules/application/application-common.ts index 32ab9dc04..2ce00a10a 100644 --- a/tns-core-modules/application/application-common.ts +++ b/tns-core-modules/application/application-common.ts @@ -70,11 +70,11 @@ export function setApplication(instance: iOSApplication | AndroidApplication): v app = instance; } -export function livesync() { +export function livesync(context?: HmrContext) { events.notify({ eventName: "livesync", object: app }); const liveSyncCore = global.__onLiveSyncCore; if (liveSyncCore) { - liveSyncCore(); + liveSyncCore(context); } } @@ -92,7 +92,7 @@ export function loadAppCss(): void { events.notify({ eventName: "loadAppCss", object: app, cssFile: getCssFileName() }); } catch (e) { throw new Error(`The file ${getCssFileName()} couldn't be loaded! ` + - `You may need to register it inside ./app/vendor.ts.`); + `You may need to register it inside ./app/vendor.ts.`); } } diff --git a/tns-core-modules/application/application.android.ts b/tns-core-modules/application/application.android.ts index 0b33bba80..6d5166675 100644 --- a/tns-core-modules/application/application.android.ts +++ b/tns-core-modules/application/application.android.ts @@ -212,12 +212,12 @@ export function getNativeApplication(): android.app.Application { return nativeApp; } -global.__onLiveSync = function () { +global.__onLiveSync = function __onLiveSync(context?: HmrContext) { if (androidApp && androidApp.paused) { return; } - livesync(); + livesync(context); }; function initLifecycleCallbacks() { diff --git a/tns-core-modules/application/application.ios.ts b/tns-core-modules/application/application.ios.ts index 867f2ef6f..85adbbccc 100644 --- a/tns-core-modules/application/application.ios.ts +++ b/tns-core-modules/application/application.ios.ts @@ -18,6 +18,7 @@ export * from "./application-common"; import { createViewFromEntry } from "../ui/builder"; import { ios as iosView, View } from "../ui/core/view"; import { Frame, NavigationEntry } from "../ui/frame"; +import { loadCss } from "../ui/styling/style-scope"; import * as utils from "../utils/utils"; import { profile, level as profilingLevel, Level } from "../profiling"; @@ -225,10 +226,21 @@ class IOSApplication implements IOSApplicationDefinition { } } - public _onLivesync(): void { - // If view can't handle livesync set window controller. - if (!this._rootView._onLivesync()) { - this.setWindowContent(); + public _onLivesync(context?: HmrContext): void { + let executeLivesync = true; + // HMR has context, livesync does not + if (context) { + if (context.module === getCssFileName()) { + loadCss(context.module); + this._rootView._onCssStateChange(); + executeLivesync = false; + } + } + if (executeLivesync) { + // If view can't handle livesync set window controller. + if (!this._rootView._onLivesync()) { + this.setWindowContent(); + } } } @@ -264,8 +276,8 @@ exports.ios = iosApp; setApplication(iosApp); // attach on global, so it can be overwritten in NativeScript Angular -(global).__onLiveSyncCore = function () { - iosApp._onLivesync(); +(global).__onLiveSyncCore = function __onLiveSyncCore(context?: HmrContext) { + iosApp._onLivesync(context); } let mainEntry: NavigationEntry; @@ -373,10 +385,10 @@ function setViewControllerView(view: View): void { } } -global.__onLiveSync = function () { +global.__onLiveSync = function __onLiveSync(context?: HmrContext) { if (!started) { return; } - livesync(); + livesync(context); } diff --git a/tns-core-modules/module.d.ts b/tns-core-modules/module.d.ts index 5fd5d161d..3d973d27f 100644 --- a/tns-core-modules/module.d.ts +++ b/tns-core-modules/module.d.ts @@ -51,8 +51,8 @@ declare namespace NodeJS { __native?: any; __inspector?: any; __extends: any; - __onLiveSync: () => void; - __onLiveSyncCore: () => void; + __onLiveSync: (context?: { type: string, module: string }) => void; + __onLiveSyncCore: (context?: { type: string, module: string }) => void; __onUncaughtError: (error: NativeScriptError) => void; TNS_WEBPACK?: boolean; __requireOverride?: (name: string, dir: string) => any; @@ -64,6 +64,27 @@ declare function clearTimeout(timeoutId: number): void; declare function setInterval(callback: (...args: any[]) => void, ms: number, ...args: any[]): number; declare function clearInterval(intervalId: number): void; +declare enum HmrType { + markup = "markup", + script = "script", + style = "style" +} + +/** + * Define a context for Hot Module Replacement. + */ +interface HmrContext { + /** + * The type of module for replacement. + */ + type: HmrType; + + /** + * The module for replacement. + */ + module: string; +} + /** * An extended JavaScript Error which will have the nativeError property initialized in case the error is caused by executing platform-specific code. */ diff --git a/tns-core-modules/ui/frame/frame.android.ts b/tns-core-modules/ui/frame/frame.android.ts index 1f56a8eb2..077d01038 100644 --- a/tns-core-modules/ui/frame/frame.android.ts +++ b/tns-core-modules/ui/frame/frame.android.ts @@ -17,6 +17,7 @@ import { _updateTransitions, _reverseTransitions, _clearEntry, _clearFragment, AnimationType } from "./fragment.transitions"; +import { loadCss } from "../styling/style-scope"; import { profile } from "../../profiling"; // TODO: Remove this and get it from global to decouple builder for angular @@ -82,13 +83,24 @@ function getAttachListener(): android.view.View.OnAttachStateChangeListener { return attachStateChangeListener; } -export function reloadPage(): void { +export function reloadPage(context?: HmrContext): void { const activity = application.android.foregroundActivity; const callbacks: AndroidActivityCallbacks = activity[CALLBACKS]; const rootView: View = callbacks.getRootView(); - if (!rootView || !rootView._onLivesync()) { - callbacks.resetActivityContent(activity); + let executeLivesync = true; + // HMR has context, livesync does not + if (context) { + if (context.module === application.getCssFileName()) { + loadCss(context.module); + rootView._onCssStateChange(); + executeLivesync = false; + } + } + if (executeLivesync) { + if (!rootView || !rootView._onLivesync()) { + callbacks.resetActivityContent(activity); + } } } @@ -469,19 +481,19 @@ export class Frame extends FrameBase { switch (this.actionBarVisibility) { case "never": return false; - + case "always": return true; - + default: if (page.actionBarHidden !== undefined) { return !page.actionBarHidden; } - + if (this._android && this._android.showActionBar !== undefined) { return this._android.showActionBar; } - + return true; } } @@ -846,14 +858,14 @@ class FragmentCallbacksImplementation implements AndroidFragmentCallbacks { // parent while its supposed parent believes it properly removed its children; in order to "force" the child to // lose its parent we temporarily add it to the parent, and then remove it (addViewInLayout doesn't trigger layout pass) const nativeView = page.nativeViewProtected; - if (nativeView != null) { - const parentView = nativeView.getParent(); + if (nativeView != null) { + const parentView = nativeView.getParent(); if (parentView instanceof android.view.ViewGroup) { if (parentView.getChildCount() === 0) { parentView.addViewInLayout(nativeView, -1, new org.nativescript.widgets.CommonLayoutParams()); } - parentView.removeView(nativeView); + parentView.removeView(nativeView); } } diff --git a/tns-core-modules/ui/page/page-common.ts b/tns-core-modules/ui/page/page-common.ts index 0d85ab1ab..738c0bfa8 100644 --- a/tns-core-modules/ui/page/page-common.ts +++ b/tns-core-modules/ui/page/page-common.ts @@ -17,17 +17,17 @@ export class PageBase extends ContentView implements PageDefinition { public static navigatedToEvent = "navigatedTo"; public static navigatingFromEvent = "navigatingFrom"; public static navigatedFromEvent = "navigatedFrom"; - + private _navigationContext: any; private _actionBar: ActionBar; public _frame: Frame; - + public actionBarHidden: boolean; public enableSwipeBackNavigation: boolean; public backgroundSpanUnderStatusBar: boolean; public hasActionBar: boolean; - + get navigationContext(): any { return this._navigationContext; } @@ -89,7 +89,7 @@ export class PageBase extends ContentView implements PageDefinition { const frame = this.parent; return frame instanceof Frame ? frame : undefined; } - + private createNavigatedData(eventName: string, isBackNavigation: boolean): NavigatedData { return { eventName: eventName, @@ -103,6 +103,10 @@ export class PageBase extends ContentView implements PageDefinition { public onNavigatingTo(context: any, isBackNavigation: boolean, bindingContext?: any) { this._navigationContext = context; + if (!this._cssState.isSelectorsLatestVersionApplied()) { + this._onCssStateChange(); + } + //https://github.com/NativeScript/NativeScript/issues/731 if (!isBackNavigation && bindingContext !== undefined && bindingContext !== null) { this.bindingContext = bindingContext; diff --git a/tns-core-modules/ui/styling/style-scope.d.ts b/tns-core-modules/ui/styling/style-scope.d.ts index b404ce9a7..b5bf01684 100644 --- a/tns-core-modules/ui/styling/style-scope.d.ts +++ b/tns-core-modules/ui/styling/style-scope.d.ts @@ -19,6 +19,11 @@ export class CssState { * Gets the static selectors that match the view and the dynamic selectors that may potentially match the view. */ public changeMap: ChangeMap; + + /** + * Checks whether style scope and CSS state selectors are in sync. + */ + public isSelectorsLatestVersionApplied(): boolean } export class StyleScope { @@ -29,6 +34,9 @@ export class StyleScope { public static createSelectorsFromImports(tree: SyntaxTree, keyframes: Object): RuleSet[]; public ensureSelectors(): number; + public isApplicationCssSelectorsLatestVersionApplied(): boolean; + public isLocalCssSelectorsLatestVersionApplied(): boolean; + public applySelectors(view: ViewBase): void public query(options: Node): SelectorCore[]; diff --git a/tns-core-modules/ui/styling/style-scope.ts b/tns-core-modules/ui/styling/style-scope.ts index 8f3cf607c..e085c2870 100644 --- a/tns-core-modules/ui/styling/style-scope.ts +++ b/tns-core-modules/ui/styling/style-scope.ts @@ -271,7 +271,7 @@ export function removeTaggedAdditionalCSS(tag: String | Number): Boolean { changed = true; } } - if (changed) { mergeCssSelectors(); } + if (changed) { mergeCssSelectors(); } return changed; } @@ -307,7 +307,7 @@ function onLiveSync(args: applicationCommon.CssChangedEventData): void { loadCss(applicationCommon.getCssFileName()); } -const loadCss = profile(`"style-scope".loadCss`, (cssFile: string) => { +export const loadCss = profile(`"style-scope".loadCss`, (cssFile: string) => { if (!cssFile) { return undefined; } @@ -343,6 +343,7 @@ export class CssState { _appliedChangeMap: Readonly>; _appliedPropertyValues: Readonly<{}>; _appliedAnimations: ReadonlyArray; + _appliedSelectorsVersion: number; _match: SelectorsMatch; _matchInvalid: boolean; @@ -367,6 +368,15 @@ export class CssState { } } + public isSelectorsLatestVersionApplied(): boolean { + if (this._appliedSelectorsVersion && this.view._styleScope) { + this.view._styleScope.ensureSelectors(); + return this.view._styleScope._getSelectorsVersion() === this._appliedSelectorsVersion; + } else { + return true; + } + } + public onLoaded(): void { if (this._matchInvalid) { this.updateMatch(); @@ -381,6 +391,7 @@ export class CssState { @profile private updateMatch() { + this._appliedSelectorsVersion = this.view._styleScope._getSelectorsVersion(); this._match = this.view._styleScope ? this.view._styleScope.matchSelectors(this.view) : CssState.emptyMatch; this._matchInvalid = false; } @@ -597,8 +608,8 @@ export class StyleScope { } public ensureSelectors(): number { - if (this._applicationCssSelectorsAppliedVersion !== applicationCssSelectorVersion || - this._localCssSelectorVersion !== this._localCssSelectorsAppliedVersion || + if (!this.isApplicationCssSelectorsLatestVersionApplied() || + !this.isLocalCssSelectorsLatestVersionApplied() || !this._mergedCssSelectors) { this._createSelectors(); @@ -607,6 +618,14 @@ export class StyleScope { return this._getSelectorsVersion(); } + public isApplicationCssSelectorsLatestVersionApplied(): boolean { + return this._applicationCssSelectorsAppliedVersion === applicationCssSelectorVersion; + } + + public isLocalCssSelectorsLatestVersionApplied(): boolean { + return this._localCssSelectorsAppliedVersion === this._localCssSelectorVersion; + } + @profile private _createSelectors() { let toMerge: RuleSet[][] = []; diff --git a/tsconfig.shared.json b/tsconfig.shared.json index eea37a566..d8fb42fd4 100644 --- a/tsconfig.shared.json +++ b/tsconfig.shared.json @@ -26,4 +26,4 @@ "tns-core-modules/*": ["tns-core-modules/*"] } } -} +} \ No newline at end of file From 790bcfb470f689f79e5892547ce237731d805e28 Mon Sep 17 00:00:00 2001 From: Vasil Chimev Date: Wed, 5 Dec 2018 14:24:24 +0200 Subject: [PATCH 02/28] refactor(HMR): apply changes in application styles at runtime --- .../application/application-common.ts | 24 +++++++++++-- .../application/application.ios.ts | 28 +++++---------- tns-core-modules/module.d.ts | 2 +- tns-core-modules/ui/frame/frame.android.ts | 34 ++++++------------- tns-core-modules/ui/page/page-common.ts | 7 ++-- tns-core-modules/ui/styling/style-scope.ts | 9 ++--- tsconfig.shared.json | 2 +- 7 files changed, 49 insertions(+), 57 deletions(-) diff --git a/tns-core-modules/application/application-common.ts b/tns-core-modules/application/application-common.ts index 2ce00a10a..3f0d0888c 100644 --- a/tns-core-modules/application/application-common.ts +++ b/tns-core-modules/application/application-common.ts @@ -32,7 +32,14 @@ export function hasLaunched(): boolean { export { Observable }; -import { UnhandledErrorEventData, iOSApplication, AndroidApplication, CssChangedEventData, LoadAppCSSEventData } from "."; +import { + AndroidApplication, + CssChangedEventData, + getRootView, + iOSApplication, + LoadAppCSSEventData, + UnhandledErrorEventData +} from "./application"; export { UnhandledErrorEventData, CssChangedEventData, LoadAppCSSEventData }; @@ -73,8 +80,19 @@ export function setApplication(instance: iOSApplication | AndroidApplication): v export function livesync(context?: HmrContext) { events.notify({ eventName: "livesync", object: app }); const liveSyncCore = global.__onLiveSyncCore; - if (liveSyncCore) { - liveSyncCore(context); + let reapplyAppCss = false + + if (context) { + const fullFileName = getCssFileName(); + const fileName = fullFileName.substring(0, fullFileName.lastIndexOf(".") + 1); + const extensions = ["css", "scss"]; + reapplyAppCss = extensions.some(ext => context.module === fileName.concat(ext)); + } + + if (reapplyAppCss) { + getRootView()._onCssStateChange(); + } else if (liveSyncCore) { + liveSyncCore(); } } diff --git a/tns-core-modules/application/application.ios.ts b/tns-core-modules/application/application.ios.ts index 85adbbccc..af6028cd4 100644 --- a/tns-core-modules/application/application.ios.ts +++ b/tns-core-modules/application/application.ios.ts @@ -18,7 +18,6 @@ export * from "./application-common"; import { createViewFromEntry } from "../ui/builder"; import { ios as iosView, View } from "../ui/core/view"; import { Frame, NavigationEntry } from "../ui/frame"; -import { loadCss } from "../ui/styling/style-scope"; import * as utils from "../utils/utils"; import { profile, level as profilingLevel, Level } from "../profiling"; @@ -162,7 +161,7 @@ class IOSApplication implements IOSApplicationDefinition { this.setWindowContent(args.root); } else { this._window = UIApplication.sharedApplication.delegate.window; - } + } } @profile @@ -226,21 +225,10 @@ class IOSApplication implements IOSApplicationDefinition { } } - public _onLivesync(context?: HmrContext): void { - let executeLivesync = true; - // HMR has context, livesync does not - if (context) { - if (context.module === getCssFileName()) { - loadCss(context.module); - this._rootView._onCssStateChange(); - executeLivesync = false; - } - } - if (executeLivesync) { - // If view can't handle livesync set window controller. - if (!this._rootView._onLivesync()) { - this.setWindowContent(); - } + public _onLivesync(): void { + // If view can't handle livesync set window controller. + if (!this._rootView._onLivesync()) { + this.setWindowContent(); } } @@ -276,8 +264,8 @@ exports.ios = iosApp; setApplication(iosApp); // attach on global, so it can be overwritten in NativeScript Angular -(global).__onLiveSyncCore = function __onLiveSyncCore(context?: HmrContext) { - iosApp._onLivesync(context); +(global).__onLiveSyncCore = function () { + iosApp._onLivesync(); } let mainEntry: NavigationEntry; @@ -391,4 +379,4 @@ global.__onLiveSync = function __onLiveSync(context?: HmrContext) { } livesync(context); -} +} \ No newline at end of file diff --git a/tns-core-modules/module.d.ts b/tns-core-modules/module.d.ts index 3d973d27f..0a0f6a033 100644 --- a/tns-core-modules/module.d.ts +++ b/tns-core-modules/module.d.ts @@ -52,7 +52,7 @@ declare namespace NodeJS { __inspector?: any; __extends: any; __onLiveSync: (context?: { type: string, module: string }) => void; - __onLiveSyncCore: (context?: { type: string, module: string }) => void; + __onLiveSyncCore: () => void; __onUncaughtError: (error: NativeScriptError) => void; TNS_WEBPACK?: boolean; __requireOverride?: (name: string, dir: string) => any; diff --git a/tns-core-modules/ui/frame/frame.android.ts b/tns-core-modules/ui/frame/frame.android.ts index 077d01038..6756bf915 100644 --- a/tns-core-modules/ui/frame/frame.android.ts +++ b/tns-core-modules/ui/frame/frame.android.ts @@ -17,7 +17,6 @@ import { _updateTransitions, _reverseTransitions, _clearEntry, _clearFragment, AnimationType } from "./fragment.transitions"; -import { loadCss } from "../styling/style-scope"; import { profile } from "../../profiling"; // TODO: Remove this and get it from global to decouple builder for angular @@ -83,24 +82,13 @@ function getAttachListener(): android.view.View.OnAttachStateChangeListener { return attachStateChangeListener; } -export function reloadPage(context?: HmrContext): void { +export function reloadPage(): void { const activity = application.android.foregroundActivity; const callbacks: AndroidActivityCallbacks = activity[CALLBACKS]; const rootView: View = callbacks.getRootView(); - let executeLivesync = true; - // HMR has context, livesync does not - if (context) { - if (context.module === application.getCssFileName()) { - loadCss(context.module); - rootView._onCssStateChange(); - executeLivesync = false; - } - } - if (executeLivesync) { - if (!rootView || !rootView._onLivesync()) { - callbacks.resetActivityContent(activity); - } + if (!rootView || !rootView._onLivesync()) { + callbacks.resetActivityContent(activity); } } @@ -481,19 +469,19 @@ export class Frame extends FrameBase { switch (this.actionBarVisibility) { case "never": return false; - + case "always": return true; - + default: if (page.actionBarHidden !== undefined) { return !page.actionBarHidden; } - + if (this._android && this._android.showActionBar !== undefined) { return this._android.showActionBar; } - + return true; } } @@ -858,14 +846,14 @@ class FragmentCallbacksImplementation implements AndroidFragmentCallbacks { // parent while its supposed parent believes it properly removed its children; in order to "force" the child to // lose its parent we temporarily add it to the parent, and then remove it (addViewInLayout doesn't trigger layout pass) const nativeView = page.nativeViewProtected; - if (nativeView != null) { - const parentView = nativeView.getParent(); + if (nativeView != null) { + const parentView = nativeView.getParent(); if (parentView instanceof android.view.ViewGroup) { if (parentView.getChildCount() === 0) { parentView.addViewInLayout(nativeView, -1, new org.nativescript.widgets.CommonLayoutParams()); } - parentView.removeView(nativeView); + parentView.removeView(nativeView); } } @@ -1210,4 +1198,4 @@ export function setActivityCallbacks(activity: android.support.v7.app.AppCompatA export function setFragmentCallbacks(fragment: android.support.v4.app.Fragment): void { fragment[CALLBACKS] = new FragmentCallbacksImplementation(); -} +} \ No newline at end of file diff --git a/tns-core-modules/ui/page/page-common.ts b/tns-core-modules/ui/page/page-common.ts index 738c0bfa8..28814e186 100644 --- a/tns-core-modules/ui/page/page-common.ts +++ b/tns-core-modules/ui/page/page-common.ts @@ -103,8 +103,11 @@ export class PageBase extends ContentView implements PageDefinition { public onNavigatingTo(context: any, isBackNavigation: boolean, bindingContext?: any) { this._navigationContext = context; - if (!this._cssState.isSelectorsLatestVersionApplied()) { - this._onCssStateChange(); + if (isBackNavigation && this._styleScope) { + this._styleScope.ensureSelectors(); + if (!this._cssState.isSelectorsLatestVersionApplied()) { + this._onCssStateChange(); + } } //https://github.com/NativeScript/NativeScript/issues/731 diff --git a/tns-core-modules/ui/styling/style-scope.ts b/tns-core-modules/ui/styling/style-scope.ts index e085c2870..c49bc5e35 100644 --- a/tns-core-modules/ui/styling/style-scope.ts +++ b/tns-core-modules/ui/styling/style-scope.ts @@ -307,7 +307,7 @@ function onLiveSync(args: applicationCommon.CssChangedEventData): void { loadCss(applicationCommon.getCssFileName()); } -export const loadCss = profile(`"style-scope".loadCss`, (cssFile: string) => { +const loadCss = profile(`"style-scope".loadCss`, (cssFile: string) => { if (!cssFile) { return undefined; } @@ -369,12 +369,7 @@ export class CssState { } public isSelectorsLatestVersionApplied(): boolean { - if (this._appliedSelectorsVersion && this.view._styleScope) { - this.view._styleScope.ensureSelectors(); - return this.view._styleScope._getSelectorsVersion() === this._appliedSelectorsVersion; - } else { - return true; - } + return this.view._styleScope._getSelectorsVersion() === this._appliedSelectorsVersion; } public onLoaded(): void { diff --git a/tsconfig.shared.json b/tsconfig.shared.json index d8fb42fd4..eea37a566 100644 --- a/tsconfig.shared.json +++ b/tsconfig.shared.json @@ -26,4 +26,4 @@ "tns-core-modules/*": ["tns-core-modules/*"] } } -} \ No newline at end of file +} From 4c15f717898a5764631211ad59bbe9f9197fdc12 Mon Sep 17 00:00:00 2001 From: Vasil Chimev Date: Thu, 6 Dec 2018 14:57:15 +0200 Subject: [PATCH 03/28] fix: iOS tests --- tns-core-modules/ui/styling/style-scope.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tns-core-modules/ui/styling/style-scope.ts b/tns-core-modules/ui/styling/style-scope.ts index c49bc5e35..a915b559d 100644 --- a/tns-core-modules/ui/styling/style-scope.ts +++ b/tns-core-modules/ui/styling/style-scope.ts @@ -386,8 +386,12 @@ export class CssState { @profile private updateMatch() { - this._appliedSelectorsVersion = this.view._styleScope._getSelectorsVersion(); - this._match = this.view._styleScope ? this.view._styleScope.matchSelectors(this.view) : CssState.emptyMatch; + if (this.view._styleScope) { + this._appliedSelectorsVersion = this.view._styleScope._getSelectorsVersion(); + this._match = this.view._styleScope.matchSelectors(this.view); + } else { + this._match = CssState.emptyMatch; + } this._matchInvalid = false; } From b9d7d6bb6294c0b658b7c5a833a9d3197530ba61 Mon Sep 17 00:00:00 2001 From: Vasil Chimev Date: Thu, 13 Dec 2018 07:34:37 +0200 Subject: [PATCH 04/28] test(HMR): apply changes in application styles at runtime --- tests/app/app/app-new.css | 3 + tests/app/app/app-new.scss | 3 + tests/app/app/application.css | 3 + tests/app/app/mainPage.ts | 8 +- tests/app/app/mainPage.xml | 2 +- tests/app/livesync/livesync-tests.ts | 120 +++++++++++++++++++++++++++ tests/app/testRunner.ts | 9 +- 7 files changed, 142 insertions(+), 6 deletions(-) create mode 100644 tests/app/app/app-new.css create mode 100644 tests/app/app/app-new.scss create mode 100644 tests/app/app/application.css create mode 100644 tests/app/livesync/livesync-tests.ts diff --git a/tests/app/app/app-new.css b/tests/app/app/app-new.css new file mode 100644 index 000000000..2b3afb687 --- /dev/null +++ b/tests/app/app/app-new.css @@ -0,0 +1,3 @@ +Button, Label { + color: green; +} diff --git a/tests/app/app/app-new.scss b/tests/app/app/app-new.scss new file mode 100644 index 000000000..2b3afb687 --- /dev/null +++ b/tests/app/app/app-new.scss @@ -0,0 +1,3 @@ +Button, Label { + color: green; +} diff --git a/tests/app/app/application.css b/tests/app/app/application.css new file mode 100644 index 000000000..119b358a7 --- /dev/null +++ b/tests/app/app/application.css @@ -0,0 +1,3 @@ +Button, Label { + color: black; +} diff --git a/tests/app/app/mainPage.ts b/tests/app/app/mainPage.ts index 70e2ce2e7..4c16fca02 100644 --- a/tests/app/app/mainPage.ts +++ b/tests/app/app/mainPage.ts @@ -2,6 +2,8 @@ import * as trace from "tns-core-modules/trace"; import * as tests from "../testRunner"; +let executeTests = true; + trace.enable(); trace.addCategories(trace.categories.Test + "," + trace.categories.Error); @@ -21,6 +23,8 @@ function runTests() { export function onNavigatedTo(args) { args.object.off(Page.loadedEvent, onNavigatedTo); - - runTests(); + if (executeTests) { + executeTests = false; + runTests(); + } } diff --git a/tests/app/app/mainPage.xml b/tests/app/app/mainPage.xml index bee9a71d8..7cead486d 100644 --- a/tests/app/app/mainPage.xml +++ b/tests/app/app/mainPage.xml @@ -1,3 +1,3 @@ - diff --git a/tests/app/livesync/livesync-tests.ts b/tests/app/livesync/livesync-tests.ts new file mode 100644 index 000000000..8916d8338 --- /dev/null +++ b/tests/app/livesync/livesync-tests.ts @@ -0,0 +1,120 @@ +import * as app from "tns-core-modules/application/application"; +import * as frame from "tns-core-modules/ui/frame"; +import * as helper from "../ui/helper"; +import * as TKUnit from "../TKUnit"; +import { Button } from "tns-core-modules/ui/button/button"; +import { Color } from "tns-core-modules/color"; +import { Page } from "tns-core-modules/ui/page"; +import { Label } from "tns-core-modules/ui/label/label"; +import { StackLayout } from "tns-core-modules/ui/layouts/stack-layout"; + +const appCssFileName = "./app/application.css"; +const appNewCssFileName = "./app/app-new.css"; +const appNewScssFileName = "./app/app-new.scss"; +const appJsFileName = "./app/app.js"; +const appTsFileName = "./app/app.ts"; +const mainPageCssFileName = "./app/main-page.css"; +const mainPageHtmlFileName = "./app/main-page.html"; +const mainPageXmlFileName = "./app/main-page.xml"; + +const green = new Color("green"); + +const mainPageFactory = function (): Page { + const page = new Page(); + const stack = new StackLayout(); + const label = new Label(); + label.id = "label"; + label.text = "label"; + stack.addChild(label); + page.content = stack; + return page; +} + +const pageFactory = function (): Page { + const page = new Page(); + const stack = new StackLayout(); + const button = new Button(); + button.id = "button"; + button.text = "button"; + stack.addChild(button); + page.content = stack; + return page; +} + +export function test_onLiveSync_HmrContext_AppStyle_AppNewCss() { + _test_onLiveSync_HmrContext_AppStyle(appNewCssFileName); +} + +export function test_onLiveSync_HmrContext_AppStyle_AppNewScss() { + _test_onLiveSync_HmrContext_AppStyle(appNewScssFileName); +} + +export function test_onLiveSync_HmrContext_ContextUndefined() { + _test_onLiveSync_HmrContext({ type: undefined, module: undefined }); +} + +export function test_onLiveSync_HmrContext_ModuleUndefined() { + _test_onLiveSync_HmrContext({ type: "script", module: undefined }); +} + +export function test_onLiveSync_HmrContext_Script_AppJs() { + _test_onLiveSync_HmrContext({ type: "script", module: appJsFileName }); +} + +export function test_onLiveSync_HmrContext_Script_AppTs() { + _test_onLiveSync_HmrContext({ type: "script", module: appTsFileName }); +} + +export function test_onLiveSync_HmrContext_Style_MainPageCss() { + _test_onLiveSync_HmrContext({ type: "style", module: mainPageCssFileName }); +} + +export function test_onLiveSync_HmrContext_Markup_MainPageHtml() { + _test_onLiveSync_HmrContext({ type: "markup", module: mainPageHtmlFileName }); +} + +export function test_onLiveSync_HmrContext_Markup_MainPageXml() { + _test_onLiveSync_HmrContext({ type: "markup", module: mainPageXmlFileName }); +} + +export function setUpModule() { + helper.navigate(mainPageFactory); +} + +export function tearDown() { + app.setCssFileName(appCssFileName); +} + +function _test_onLiveSync_HmrContext_AppStyle(styleFileName: string) { + const pageBeforeNavigation = helper.getCurrentPage(); + + helper.navigateWithHistory(pageFactory); + app.setCssFileName(styleFileName); + + const pageBeforeLiveSync = helper.getCurrentPage(); + global.__onLiveSync({ type: "style", module: styleFileName }); + + const pageAfterLiveSync = helper.getCurrentPage(); + TKUnit.waitUntilReady(() => pageAfterLiveSync.getViewById("button").style.color.toString() === green.toString()); + + TKUnit.assertTrue(pageAfterLiveSync.frame.canGoBack(), "App styles NOT applied - livesync navigation executed!"); + TKUnit.assertEqual(pageAfterLiveSync, pageBeforeLiveSync, "Pages are different - livesync navigation executed!"); + TKUnit.assertTrue(pageAfterLiveSync._cssState.isSelectorsLatestVersionApplied(), "Latest selectors version NOT applied!"); + + helper.goBack(); + + const pageAfterNavigationBack = helper.getCurrentPage(); + TKUnit.assertEqual(pageAfterNavigationBack.getViewById("label").style.color, green, "App styles NOT applied on back navigation!"); + TKUnit.assertEqual(pageBeforeNavigation, pageAfterNavigationBack, "Pages are different - livesync navigation executed!"); + TKUnit.assertTrue(pageAfterNavigationBack._cssState.isSelectorsLatestVersionApplied(), "Latest selectors version is NOT applied!"); +} + +function _test_onLiveSync_HmrContext(context: { type, module }) { + helper.navigateWithHistory(pageFactory); + global.__onLiveSync({ type: context.type, module: context.module }); + + TKUnit.waitUntilReady(() => !!frame.topmost()); + const topmostFrame = frame.topmost(); + TKUnit.waitUntilReady(() => topmostFrame.currentPage && topmostFrame.currentPage.isLoaded && !topmostFrame.canGoBack()); + TKUnit.assertTrue(topmostFrame.currentPage.getViewById("label").isLoaded); +} \ No newline at end of file diff --git a/tests/app/testRunner.ts b/tests/app/testRunner.ts index a119642a0..b96bde95d 100644 --- a/tests/app/testRunner.ts +++ b/tests/app/testRunner.ts @@ -153,9 +153,6 @@ allTests["STYLE-PROPERTIES"] = stylePropertiesTests; import * as frameTests from "./ui/frame/frame-tests"; allTests["FRAME"] = frameTests; -import * as tabViewRootTests from "./ui/tab-view/tab-view-root-tests"; -allTests["TAB-VIEW-ROOT"] = tabViewRootTests; - import * as viewTests from "./ui/view/view-tests"; allTests["VIEW"] = viewTests; @@ -255,6 +252,12 @@ allTests["SEARCH-BAR"] = searchBarTests; import * as navigationTests from "./navigation/navigation-tests"; allTests["NAVIGATION"] = navigationTests; +import * as livesyncTests from "./livesync/livesync-tests"; +allTests["LIVESYNC"] = livesyncTests; + +import * as tabViewRootTests from "./ui/tab-view/tab-view-root-tests"; +allTests["TAB-VIEW-ROOT"] = tabViewRootTests; + import * as resetRootViewTests from "./ui/root-view/reset-root-view-tests"; allTests["RESET-ROOT-VIEW"] = resetRootViewTests; From c404a3803861615c533dcd54f09498808addbd4d Mon Sep 17 00:00:00 2001 From: Vasil Chimev Date: Thu, 13 Dec 2018 17:19:23 +0200 Subject: [PATCH 05/28] refactor: tests to parce templates --- tests/app/livesync/livesync-tests.ts | 45 ++++++++++++---------------- 1 file changed, 19 insertions(+), 26 deletions(-) diff --git a/tests/app/livesync/livesync-tests.ts b/tests/app/livesync/livesync-tests.ts index 8916d8338..8ae772203 100644 --- a/tests/app/livesync/livesync-tests.ts +++ b/tests/app/livesync/livesync-tests.ts @@ -2,11 +2,9 @@ import * as app from "tns-core-modules/application/application"; import * as frame from "tns-core-modules/ui/frame"; import * as helper from "../ui/helper"; import * as TKUnit from "../TKUnit"; -import { Button } from "tns-core-modules/ui/button/button"; import { Color } from "tns-core-modules/color"; +import { parse } from "tns-core-modules/ui/builder"; import { Page } from "tns-core-modules/ui/page"; -import { Label } from "tns-core-modules/ui/label/label"; -import { StackLayout } from "tns-core-modules/ui/layouts/stack-layout"; const appCssFileName = "./app/application.css"; const appNewCssFileName = "./app/app-new.css"; @@ -19,27 +17,19 @@ const mainPageXmlFileName = "./app/main-page.xml"; const green = new Color("green"); -const mainPageFactory = function (): Page { - const page = new Page(); - const stack = new StackLayout(); - const label = new Label(); - label.id = "label"; - label.text = "label"; - stack.addChild(label); - page.content = stack; - return page; -} +const mainPageTemplate = ` + + + + + `; -const pageFactory = function (): Page { - const page = new Page(); - const stack = new StackLayout(); - const button = new Button(); - button.id = "button"; - button.text = "button"; - stack.addChild(button); - page.content = stack; - return page; -} +const pageTemplate = ` + + + + + `; export function test_onLiveSync_HmrContext_AppStyle_AppNewCss() { _test_onLiveSync_HmrContext_AppStyle(appNewCssFileName); @@ -78,7 +68,8 @@ export function test_onLiveSync_HmrContext_Markup_MainPageXml() { } export function setUpModule() { - helper.navigate(mainPageFactory); + const mainPage = parse(mainPageTemplate); + helper.navigate(() => mainPage); } export function tearDown() { @@ -88,7 +79,8 @@ export function tearDown() { function _test_onLiveSync_HmrContext_AppStyle(styleFileName: string) { const pageBeforeNavigation = helper.getCurrentPage(); - helper.navigateWithHistory(pageFactory); + const page = parse(pageTemplate); + helper.navigateWithHistory(() => page); app.setCssFileName(styleFileName); const pageBeforeLiveSync = helper.getCurrentPage(); @@ -110,7 +102,8 @@ function _test_onLiveSync_HmrContext_AppStyle(styleFileName: string) { } function _test_onLiveSync_HmrContext(context: { type, module }) { - helper.navigateWithHistory(pageFactory); + const page = parse(pageTemplate); + helper.navigateWithHistory(() => page); global.__onLiveSync({ type: context.type, module: context.module }); TKUnit.waitUntilReady(() => !!frame.topmost()); From 3481e6f33ff31da530b35ee2550b91fdf4221e1e Mon Sep 17 00:00:00 2001 From: Nathan Walker Date: Mon, 17 Dec 2018 01:33:12 -0800 Subject: [PATCH 06/28] feat(image-cache): expose onError callback (#6458) * feat(Cache): better error handling * refactor(image-cache): add `error` parameter to `_onDownloadError` Add DownloadError interface. * refactor(image-cache): updates for iOS Use arrow functions. Remove an unnecessary `trace.write(). * refactor(image-cache): updates for Android Update Android `constructor()`. Move `key` and `image` check to `set()`. Update `trace.write`. * fix(image-cache): onError handling --- .../http/http-request/http-request.android.ts | 13 ++++- .../ui/image-cache/image-cache-common.ts | 50 ++++++++++++++++--- .../ui/image-cache/image-cache.android.ts | 21 +++++++- .../ui/image-cache/image-cache.d.ts | 36 ++++++++++++- .../ui/image-cache/image-cache.ios.ts | 15 ++++-- .../android/org.nativescript.widgets.d.ts | 2 + 6 files changed, 120 insertions(+), 17 deletions(-) diff --git a/tns-core-modules/http/http-request/http-request.android.ts b/tns-core-modules/http/http-request/http-request.android.ts index 0877e6d0d..ff986956f 100644 --- a/tns-core-modules/http/http-request/http-request.android.ts +++ b/tns-core-modules/http/http-request/http-request.android.ts @@ -52,7 +52,10 @@ function ensureCompleteCallback() { onComplete: function (result: any, context: any) { // as a context we will receive the id of the request onRequestComplete(context, result); - } + }, + onError: function (error: string, context: any) { + onRequestError(error, context); + }, }); } @@ -148,6 +151,14 @@ function onRequestComplete(requestId: number, result: org.nativescript.widgets.A }); } +function onRequestError(error: string, requestId: number) { + var callbacks = pendingRequests[requestId]; + delete pendingRequests[requestId]; + if (callbacks) { + callbacks.rejectCallback(new Error(error)); + } +} + function buildJavaOptions(options: http.HttpRequestOptions) { if (typeof options.url !== "string") { throw new Error("Http request must provide a valid url."); diff --git a/tns-core-modules/ui/image-cache/image-cache-common.ts b/tns-core-modules/ui/image-cache/image-cache-common.ts index b505a390d..3dbd50809 100644 --- a/tns-core-modules/ui/image-cache/image-cache-common.ts +++ b/tns-core-modules/ui/image-cache/image-cache-common.ts @@ -6,10 +6,12 @@ export interface DownloadRequest { url: string; key: string; completed?: (image: any, key: string) => void; + error?: (key: string) => void; } export class Cache extends observable.Observable implements definition.Cache { public static downloadedEvent = "downloaded"; + public static downloadErrorEvent = "downloadError"; public placeholder: imageSource.ImageSource; public maxRequests = 5; @@ -93,6 +95,20 @@ export class Cache extends observable.Observable implements definition.Cache { else { existingRequest.completed = newRequest.completed; } + if (existingRequest.error) { + if (newRequest.error) { + var existingError = existingRequest.error; + var stackError = function (key: string) { + existingError(key); + newRequest.error(key); + } + + existingRequest.error = stackError; + } + } + else { + existingRequest.error = newRequest.error; + } } public get(key: string): any { @@ -125,10 +141,7 @@ export class Cache extends observable.Observable implements definition.Cache { public _onDownloadCompleted(key: string, image: any) { var request = this._pendingDownloads[key]; - if (request.key && image) { - this.set(request.key, image); - } - + this.set(request.key, image); this._currentDownloads--; if (request.completed) { @@ -140,7 +153,29 @@ export class Cache extends observable.Observable implements definition.Cache { eventName: Cache.downloadedEvent, object: this, key: key, - image: image + image: image + }); + } + + delete this._pendingDownloads[request.key]; + + this._updateQueue(); + } + + public _onDownloadError(key: string, err: Error) { + var request = this._pendingDownloads[key]; + this._currentDownloads--; + + if (request.error) { + request.error(request.key); + } + + if (this.hasListeners(Cache.downloadErrorEvent)) { + this.notify({ + eventName: Cache.downloadErrorEvent, + object: this, + key: key, + error: err }); } @@ -185,6 +220,7 @@ export class Cache extends observable.Observable implements definition.Cache { } } export interface Cache { - on(eventNames: string, callback: (args: observable.EventData) => void , thisArg?: any); - on(event: "downloaded", callback: (args: definition.DownloadedData) => void , thisArg?: any); + on(eventNames: string, callback: (args: observable.EventData) => void, thisArg?: any); + on(event: "downloaded", callback: (args: definition.DownloadedData) => void, thisArg?: any); + on(event: "downloadError", callback: (args: definition.DownloadError) => void, thisArg?: any); } \ No newline at end of file diff --git a/tns-core-modules/ui/image-cache/image-cache.android.ts b/tns-core-modules/ui/image-cache/image-cache.android.ts index 0a6e4e94f..96118aeed 100644 --- a/tns-core-modules/ui/image-cache/image-cache.android.ts +++ b/tns-core-modules/ui/image-cache/image-cache.android.ts @@ -1,4 +1,5 @@ import * as common from "./image-cache-common"; +import * as trace from "../../trace"; var LruBitmapCacheClass; function ensureLruBitmapCacheClass() { @@ -45,7 +46,17 @@ export class Cache extends common.Cache { onComplete: function (result: any, context: any) { var instance = that.get(); if (instance) { - instance._onDownloadCompleted(context, result) + if (result) { + instance._onDownloadCompleted(context, result); + } else { + instance._onDownloadError(context, new Error("No result in CompletionCallback")); + } + } + }, + onError: function (err: string, context: any) { + var instance = that.get(); + if (instance) { + instance._onDownloadError(context, new Error(err)); } } }); @@ -61,7 +72,13 @@ export class Cache extends common.Cache { } public set(key: string, image: any): void { - this._cache.put(key, image); + try { + if (key && image) { + this._cache.put(key, image); + } + } catch (err) { + trace.write("Cache set error: " + err, trace.categories.Error, trace.messageType.error); + } } public remove(key: string): void { diff --git a/tns-core-modules/ui/image-cache/image-cache.d.ts b/tns-core-modules/ui/image-cache/image-cache.d.ts index 8d909bf31..2a697f964 100644 --- a/tns-core-modules/ui/image-cache/image-cache.d.ts +++ b/tns-core-modules/ui/image-cache/image-cache.d.ts @@ -22,6 +22,10 @@ export interface DownloadRequest { * An optional function to be called when the download is complete. */ completed?: (image: any, key: string) => void; + /** + * An optional function to be called if the download errors. + */ + error?: (key: string) => void; } /** @@ -32,6 +36,10 @@ export class Cache extends observable.Observable { * String value used when hooking to downloaded event. */ public static downloadedEvent: string; + /** + * String value used when hooking to download error event. + */ + public static downloadErrorEvent: string; /** * The image to be used to notify for a pending download request - e.g. loading indicator. */ @@ -82,12 +90,17 @@ export class Cache extends observable.Observable { * @param callback - Callback function which will be executed when event is raised. * @param thisArg - An optional parameter which will be used as `this` context for callback execution. */ - on(eventNames: string, callback: (args: observable.EventData) => void , thisArg?: any); + on(eventNames: string, callback: (args: observable.EventData) => void, thisArg?: any); /** * Raised when the image has been downloaded. */ - on(event: "downloaded", callback: (args: DownloadedData) => void , thisArg?: any); + on(event: "downloaded", callback: (args: DownloadedData) => void, thisArg?: any); + + /** + * Raised if the image download errors. + */ + on(event: "downloadError", callback: (args: DownloadError) => void, thisArg?: any); //@private /** @@ -99,6 +112,11 @@ export class Cache extends observable.Observable { */ _onDownloadCompleted(key: string, image: any); //@endprivate + /** + * @private + */ + _onDownloadError(key: string, err: Error); + //@endprivate } /** @@ -114,3 +132,17 @@ export interface DownloadedData extends observable.EventData { */ image: imageSource.ImageSource; } + +/** + * Provides data for download error. + */ +export interface DownloadError extends observable.EventData { + /** + * A string indentifier of the cached image. + */ + key: string; + /** + * Gets the error. + */ + error: Error; +} diff --git a/tns-core-modules/ui/image-cache/image-cache.ios.ts b/tns-core-modules/ui/image-cache/image-cache.ios.ts index 41f475c67..8224fcb56 100644 --- a/tns-core-modules/ui/image-cache/image-cache.ios.ts +++ b/tns-core-modules/ui/image-cache/image-cache.ios.ts @@ -73,7 +73,7 @@ export class Cache extends common.Cache { super(); this._cache = new NSCache(); - + //this._delegate = NSCacheDelegateImpl.new(); //this._cache.delegate = this._delegate; @@ -83,11 +83,16 @@ export class Cache extends common.Cache { public _downloadCore(request: common.DownloadRequest) { ensureHttpRequest(); - var that = this; httpRequest.request({ url: request.url, method: "GET" }) - .then(response => { - var image = UIImage.alloc().initWithData(response.content.raw); - that._onDownloadCompleted(request.key, image); + .then((response) => { + try { + var image = UIImage.alloc().initWithData(response.content.raw); + this._onDownloadCompleted(request.key, image); + } catch (err) { + this._onDownloadError(request.key, err); + } + }, (err) => { + this._onDownloadError(request.key, err); }); } diff --git a/tns-platform-declarations/android/org.nativescript.widgets.d.ts b/tns-platform-declarations/android/org.nativescript.widgets.d.ts index ae96b44f3..053e9c728 100644 --- a/tns-platform-declarations/android/org.nativescript.widgets.d.ts +++ b/tns-platform-declarations/android/org.nativescript.widgets.d.ts @@ -5,10 +5,12 @@ export class CompleteCallback { constructor(implementation: ICompleteCallback); onComplete(result: Object, context: Object): void; + onError(error: string, context: Object): void; } export interface ICompleteCallback { onComplete(result: Object, context: Object): void; + onError(error: string, context: Object): void; } export module Image { From c034d6ead66a3c23d5eb074e864a5d76997069d5 Mon Sep 17 00:00:00 2001 From: Manol Donev Date: Mon, 17 Dec 2018 15:27:52 +0200 Subject: [PATCH 07/28] fix(android): animator restore logic on simulated nav (#6710) --- tns-core-modules/ui/frame/frame.android.ts | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/tns-core-modules/ui/frame/frame.android.ts b/tns-core-modules/ui/frame/frame.android.ts index 6756bf915..28967e222 100644 --- a/tns-core-modules/ui/frame/frame.android.ts +++ b/tns-core-modules/ui/frame/frame.android.ts @@ -527,10 +527,22 @@ function getAnimatorState(entry: BackstackEntry): AnimatorState { function restoreAnimatorState(entry: BackstackEntry, snapshot: AnimatorState): void { const expandedEntry = entry; - expandedEntry.enterAnimator = snapshot.enterAnimator; - expandedEntry.exitAnimator = snapshot.exitAnimator; - expandedEntry.popEnterAnimator = snapshot.popEnterAnimator; - expandedEntry.popExitAnimator = snapshot.popExitAnimator; + if (snapshot.enterAnimator) { + expandedEntry.enterAnimator = snapshot.enterAnimator; + } + + if (snapshot.exitAnimator) { + expandedEntry.exitAnimator = snapshot.exitAnimator; + } + + if (snapshot.popEnterAnimator) { + expandedEntry.popEnterAnimator = snapshot.popEnterAnimator; + } + + if (snapshot.popExitAnimator) { + expandedEntry.popExitAnimator = snapshot.popExitAnimator; + } + expandedEntry.transitionName = snapshot.transitionName; } From 89870f7c91e69cad053b89a44b0fd39c5e598717 Mon Sep 17 00:00:00 2001 From: Martin Bektchiev Date: Mon, 17 Dec 2018 17:05:09 +0200 Subject: [PATCH 08/28] chore(docs): Upgrade typedoc to version 0.13.0 (#6717) Building with the current 0.5.10 now fails because it depends on typescript before 2.4. This causes the following errors: ``` NativeScript@ typedoc /root/NativeScript > typedoc --tsconfig tsconfig.typedoc.json --out bin/dist/apiref --includeDeclarations --name NativeScript --theme ./node_modules/nativescript-typedoc-theme --excludeExternals --externalPattern "**/+(tns-core-modules|module).d.ts" Loaded plugin typedoc-plugin-external-module-name Using TypeScript 2.2.2 from /root/NativeScript/node_modules/typedoc/node_modules/typescript/lib Error: /root/NativeScript/tns-core-modules/module.d.ts(67) In ambient enum declarations member initializer must be constant expression. Error: /root/NativeScript/tns-core-modules/module.d.ts(68) In ambient enum declarations member initializer must be constant expression. Error: /root/NativeScript/tns-core-modules/module.d.ts(69) In ambient enum declarations member initializer must be constant expression. ``` This fix is required to support typeodoc@0.8.0 and above: https://github.com/NativeScript/nativescript-typedoc-theme/commit/01f94b4ae2ec1b617eec72b2c325f68c390ad091 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index cbd61d119..1490478c2 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,7 @@ "time-grunt": "1.3.0", "tslib": "^1.9.3", "tslint": "^5.4.3", - "typedoc": "^0.5.10", + "typedoc": "^0.13.0", "typedoc-plugin-external-module-name": "git://github.com/PanayotCankov/typedoc-plugin-external-module-name.git#with-js", "typescript": "^3.1.6" }, From 4dc35a5e6ff122e6eb20e4de91eba1765d124f00 Mon Sep 17 00:00:00 2001 From: Manol Donev Date: Tue, 18 Dec 2018 10:23:02 +0200 Subject: [PATCH 09/28] fix(android): failure saving state in mixed parent/nested frame nav (#6719) --- tns-core-modules/ui/frame/frame.android.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tns-core-modules/ui/frame/frame.android.ts b/tns-core-modules/ui/frame/frame.android.ts index 28967e222..d2e3c9943 100644 --- a/tns-core-modules/ui/frame/frame.android.ts +++ b/tns-core-modules/ui/frame/frame.android.ts @@ -903,6 +903,12 @@ class FragmentCallbacksImplementation implements AndroidFragmentCallbacks { return null; } + // [nested frames / fragments] see https://github.com/NativeScript/NativeScript/issues/6629 + // retaining reference to a destroyed fragment here somehow causes a cryptic + // "IllegalStateException: Failure saving state: active fragment has cleared index: -1" + // in a specific mixed parent / nested frame navigation scenario + entry.fragment = null; + const page = entry.resolvedPage; if (!page) { traceError(`${fragment}.onDestroy: entry has no resolvedPage`); From 961b03ecefafee0d2102b8affdee7a7683a4cc7a Mon Sep 17 00:00:00 2001 From: Manol Donev Date: Tue, 18 Dec 2018 10:25:32 +0200 Subject: [PATCH 10/28] chore: temporarily disable e2e tests with mixed animation nav (#6720) --- .../e2e/layout-root.e2e-spec.ts | 337 +++++++++--------- 1 file changed, 169 insertions(+), 168 deletions(-) diff --git a/e2e/nested-frame-navigation/e2e/layout-root.e2e-spec.ts b/e2e/nested-frame-navigation/e2e/layout-root.e2e-spec.ts index b1e7c44a9..0cda701ee 100644 --- a/e2e/nested-frame-navigation/e2e/layout-root.e2e-spec.ts +++ b/e2e/nested-frame-navigation/e2e/layout-root.e2e-spec.ts @@ -1,4 +1,5 @@ import { AppiumDriver, createDriver } from "nativescript-dev-appium"; + import { Screen, playersData, home, somePage, otherPage, teamsData } from "./screen"; import * as shared from "./shared.e2e-spec"; import { suspendTime, appSuspendResume, dontKeepActivities, transitions } from "./config"; @@ -261,223 +262,223 @@ describe("layout-root:", () => { }); }); - describe("players list slide transition with parent frame default transition:", () => { - const playerOne = playersData["playerOneSlide"]; - const playerTwo = playersData["playerTwoSlide"]; + // describe("players list slide transition with parent frame default transition:", () => { + // const playerOne = playersData["playerOneSlide"]; + // const playerTwo = playersData["playerTwoSlide"]; - it("loaded layout root with nested frames", async () => { - await screen.navigateToLayoutWithFrame(); - await screen.loadedLayoutWithFrame(); - }); + // it("loaded layout root with nested frames", async () => { + // await screen.navigateToLayoutWithFrame(); + // await screen.loadedLayoutWithFrame(); + // }); - it("loaded players list", async () => { - await screen.loadedPlayersList(); - }); + // it("loaded players list", async () => { + // await screen.loadedPlayersList(); + // }); - it("loaded player details with slide", async () => { - await shared.testPlayerNavigated(playerTwo, screen); + // it("loaded player details with slide", async () => { + // await shared.testPlayerNavigated(playerTwo, screen); - if (appSuspendResume) { - await driver.backgroundApp(suspendTime); - await driver.waitForElement(playerTwo.name); // wait for player - } - }); + // if (appSuspendResume) { + // await driver.backgroundApp(suspendTime); + // await driver.waitForElement(playerTwo.name); // wait for player + // } + // }); - it("navigate parent frame and go back", async () => { - await shared.testSomePageNavigatedDefault(screen); + // it("navigate parent frame and go back", async () => { + // await shared.testSomePageNavigatedDefault(screen); - if (appSuspendResume) { - await driver.backgroundApp(suspendTime); - await driver.waitForElement(somePage); // wait for some page - } + // if (appSuspendResume) { + // await driver.backgroundApp(suspendTime); + // await driver.waitForElement(somePage); // wait for some page + // } - await driver.navBack(); // some page back navigation + // await driver.navBack(); // some page back navigation - if (appSuspendResume) { - await driver.backgroundApp(suspendTime); - await driver.waitForElement(playerTwo.name); // wait for player - } + // if (appSuspendResume) { + // await driver.backgroundApp(suspendTime); + // await driver.waitForElement(playerTwo.name); // wait for player + // } - await screen.loadedPlayerDetails(playerTwo); - }); + // await screen.loadedPlayerDetails(playerTwo); + // }); - it("loaded player list", async () => { - await screen.goBackToPlayersList(); + // it("loaded player list", async () => { + // await screen.goBackToPlayersList(); - if (appSuspendResume) { - await driver.backgroundApp(suspendTime); - await driver.waitForElement(playerOne.name); // wait for players list - } - }); + // if (appSuspendResume) { + // await driver.backgroundApp(suspendTime); + // await driver.waitForElement(playerOne.name); // wait for players list + // } + // }); - it("loaded home page again", async () => { - await screen.resetToHome(); - await screen.loadedHome(); - }); - }); + // it("loaded home page again", async () => { + // await screen.resetToHome(); + // await screen.loadedHome(); + // }); + // }); - describe("players list slide transition with parent frame no transition:", () => { - const playerOne = playersData["playerOneSlide"]; - const playerTwo = playersData["playerTwoSlide"]; + // describe("players list slide transition with parent frame no transition:", () => { + // const playerOne = playersData["playerOneSlide"]; + // const playerTwo = playersData["playerTwoSlide"]; - it("loaded layout root with nested frames", async () => { - await screen.navigateToLayoutWithFrame(); - await screen.loadedLayoutWithFrame(); - }); + // it("loaded layout root with nested frames", async () => { + // await screen.navigateToLayoutWithFrame(); + // await screen.loadedLayoutWithFrame(); + // }); - it("loaded players list", async () => { - await screen.loadedPlayersList(); - }); + // it("loaded players list", async () => { + // await screen.loadedPlayersList(); + // }); - it("loaded player details with slide", async () => { - await shared.testPlayerNavigated(playerTwo, screen); + // it("loaded player details with slide", async () => { + // await shared.testPlayerNavigated(playerTwo, screen); - if (appSuspendResume) { - await driver.backgroundApp(suspendTime); - await driver.waitForElement(playerTwo.name); // wait for player - } - }); + // if (appSuspendResume) { + // await driver.backgroundApp(suspendTime); + // await driver.waitForElement(playerTwo.name); // wait for player + // } + // }); - it("navigate parent frame and go back", async () => { - await shared.testSomePageNavigatedNone(screen); + // it("navigate parent frame and go back", async () => { + // await shared.testSomePageNavigatedNone(screen); - if (appSuspendResume) { - await driver.backgroundApp(suspendTime); - await driver.waitForElement(somePage); // wait for some page - } + // if (appSuspendResume) { + // await driver.backgroundApp(suspendTime); + // await driver.waitForElement(somePage); // wait for some page + // } - await driver.navBack(); // some page back navigation + // await driver.navBack(); // some page back navigation - if (appSuspendResume) { - await driver.backgroundApp(suspendTime); - await driver.waitForElement(playerTwo.name); // wait for player - } + // if (appSuspendResume) { + // await driver.backgroundApp(suspendTime); + // await driver.waitForElement(playerTwo.name); // wait for player + // } - await screen.loadedPlayerDetails(playerTwo); - }); + // await screen.loadedPlayerDetails(playerTwo); + // }); - it("loaded player list", async () => { - await screen.goBackToPlayersList(); + // it("loaded player list", async () => { + // await screen.goBackToPlayersList(); - if (appSuspendResume) { - await driver.backgroundApp(suspendTime); - await driver.waitForElement(playerOne.name); // wait for players list - } - }); + // if (appSuspendResume) { + // await driver.backgroundApp(suspendTime); + // await driver.waitForElement(playerOne.name); // wait for players list + // } + // }); - it("loaded home page again", async () => { - await screen.resetToHome(); - await screen.loadedHome(); - }); - }); + // it("loaded home page again", async () => { + // await screen.resetToHome(); + // await screen.loadedHome(); + // }); + // }); - describe("players list flip transition with parent frame default transition:", () => { - const playerOne = playersData["playerOneFlip"]; - const playerTwo = playersData["playerTwoFlip"]; + // describe("players list flip transition with parent frame default transition:", () => { + // const playerOne = playersData["playerOneFlip"]; + // const playerTwo = playersData["playerTwoFlip"]; - it("loaded layout root with nested frames", async () => { - await screen.navigateToLayoutWithFrame(); - await screen.loadedLayoutWithFrame(); - }); + // it("loaded layout root with nested frames", async () => { + // await screen.navigateToLayoutWithFrame(); + // await screen.loadedLayoutWithFrame(); + // }); - it("loaded players list", async () => { - await screen.loadedPlayersList(); - }); + // it("loaded players list", async () => { + // await screen.loadedPlayersList(); + // }); - it("loaded player details with slide", async () => { - await shared.testPlayerNavigated(playerTwo, screen); + // it("loaded player details with slide", async () => { + // await shared.testPlayerNavigated(playerTwo, screen); - if (appSuspendResume) { - await driver.backgroundApp(suspendTime); - await driver.waitForElement(playerTwo.name); // wait for player - } - }); + // if (appSuspendResume) { + // await driver.backgroundApp(suspendTime); + // await driver.waitForElement(playerTwo.name); // wait for player + // } + // }); - it("navigate parent frame and go back", async () => { - await shared.testSomePageNavigatedDefault(screen); + // it("navigate parent frame and go back", async () => { + // await shared.testSomePageNavigatedDefault(screen); - if (appSuspendResume) { - await driver.backgroundApp(suspendTime); - await driver.waitForElement(somePage); // wait for some page - } + // if (appSuspendResume) { + // await driver.backgroundApp(suspendTime); + // await driver.waitForElement(somePage); // wait for some page + // } - await driver.navBack(); // some page back navigation + // await driver.navBack(); // some page back navigation - if (appSuspendResume) { - await driver.backgroundApp(suspendTime); - await driver.waitForElement(playerTwo.name); // wait for player - } + // if (appSuspendResume) { + // await driver.backgroundApp(suspendTime); + // await driver.waitForElement(playerTwo.name); // wait for player + // } - await screen.loadedPlayerDetails(playerTwo); - }); + // await screen.loadedPlayerDetails(playerTwo); + // }); - it("loaded player list", async () => { - await screen.goBackToPlayersList(); + // it("loaded player list", async () => { + // await screen.goBackToPlayersList(); - if (appSuspendResume) { - await driver.backgroundApp(suspendTime); - await driver.waitForElement(playerOne.name); // wait for players list - } - }); + // if (appSuspendResume) { + // await driver.backgroundApp(suspendTime); + // await driver.waitForElement(playerOne.name); // wait for players list + // } + // }); - it("loaded home page again", async () => { - await screen.resetToHome(); - await screen.loadedHome(); - }); - }); + // it("loaded home page again", async () => { + // await screen.resetToHome(); + // await screen.loadedHome(); + // }); + // }); - describe("players list flip transition with parent frame no transition:", () => { - const playerOne = playersData["playerOneFlip"]; - const playerTwo = playersData["playerTwoFlip"]; + // describe("players list flip transition with parent frame no transition:", () => { + // const playerOne = playersData["playerOneFlip"]; + // const playerTwo = playersData["playerTwoFlip"]; - it("loaded layout root with nested frames", async () => { - await screen.navigateToLayoutWithFrame(); - await screen.loadedLayoutWithFrame(); - }); + // it("loaded layout root with nested frames", async () => { + // await screen.navigateToLayoutWithFrame(); + // await screen.loadedLayoutWithFrame(); + // }); - it("loaded players list", async () => { - await screen.loadedPlayersList(); - }); + // it("loaded players list", async () => { + // await screen.loadedPlayersList(); + // }); - it("loaded player details with slide", async () => { - await shared.testPlayerNavigated(playerTwo, screen); + // it("loaded player details with slide", async () => { + // await shared.testPlayerNavigated(playerTwo, screen); - if (appSuspendResume) { - await driver.backgroundApp(suspendTime); - await driver.waitForElement(playerTwo.name); // wait for player - } - }); + // if (appSuspendResume) { + // await driver.backgroundApp(suspendTime); + // await driver.waitForElement(playerTwo.name); // wait for player + // } + // }); - it("navigate parent frame and go back", async () => { - await shared.testSomePageNavigatedNone(screen); + // it("navigate parent frame and go back", async () => { + // await shared.testSomePageNavigatedNone(screen); - if (appSuspendResume) { - await driver.backgroundApp(suspendTime); - await driver.waitForElement(somePage); // wait for some page - } + // if (appSuspendResume) { + // await driver.backgroundApp(suspendTime); + // await driver.waitForElement(somePage); // wait for some page + // } - await driver.navBack(); // some page back navigation + // await driver.navBack(); // some page back navigation - if (appSuspendResume) { - await driver.backgroundApp(suspendTime); - await driver.waitForElement(playerTwo.name); // wait for player - } + // if (appSuspendResume) { + // await driver.backgroundApp(suspendTime); + // await driver.waitForElement(playerTwo.name); // wait for player + // } - await screen.loadedPlayerDetails(playerTwo); - }); + // await screen.loadedPlayerDetails(playerTwo); + // }); - it("loaded player list", async () => { - await screen.goBackToPlayersList(); + // it("loaded player list", async () => { + // await screen.goBackToPlayersList(); - if (appSuspendResume) { - await driver.backgroundApp(suspendTime); - await driver.waitForElement(playerOne.name); // wait for players list - } - }); + // if (appSuspendResume) { + // await driver.backgroundApp(suspendTime); + // await driver.waitForElement(playerOne.name); // wait for players list + // } + // }); - it("loaded home page again", async () => { - await screen.resetToHome(); - await screen.loadedHome(); - }); - }); + // it("loaded home page again", async () => { + // await screen.resetToHome(); + // await screen.loadedHome(); + // }); + // }); }); From db4f9f5ddb3ffd9d56e61e59fc0a5eb1d7cf8694 Mon Sep 17 00:00:00 2001 From: Darin Dimitrov Date: Tue, 18 Dec 2018 14:23:27 +0200 Subject: [PATCH 11/28] Fix some lint errors --- apps/app/css-perf-test/main-page.ts | 2 +- apps/app/cuteness.io/main-page.ts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/app/css-perf-test/main-page.ts b/apps/app/css-perf-test/main-page.ts index c22a93868..eccc8d67c 100644 --- a/apps/app/css-perf-test/main-page.ts +++ b/apps/app/css-perf-test/main-page.ts @@ -1,4 +1,4 @@ -import {EventData as ObservableEventData } from "tns-core-modules/data/observable"; +import { EventData as ObservableEventData } from "tns-core-modules/data/observable"; export function navigatedTo(args: ObservableEventData) { setTimeout(() => { diff --git a/apps/app/cuteness.io/main-page.ts b/apps/app/cuteness.io/main-page.ts index 6fc3b9429..b2a89b2c3 100644 --- a/apps/app/cuteness.io/main-page.ts +++ b/apps/app/cuteness.io/main-page.ts @@ -1,7 +1,7 @@ -import {EventData as ObservableEventData } from "tns-core-modules/data/observable"; +import { EventData as ObservableEventData } from "tns-core-modules/data/observable"; import { Page } from "tns-core-modules/ui/page"; -import {ItemEventData as ListViewItemEventData } from "tns-core-modules/ui/list-view"; -import {topmost as topmostFrame } from "tns-core-modules/ui/frame"; +import { ItemEventData as ListViewItemEventData } from "tns-core-modules/ui/list-view"; +import { topmost as topmostFrame } from "tns-core-modules/ui/frame"; import { AppViewModel } from "./reddit-app-view-model"; var appViewModel = new AppViewModel(); From 8a32102fa130fb2b9c3aba9656ccb7d0b04e0c21 Mon Sep 17 00:00:00 2001 From: Alexander Vakrilov Date: Thu, 20 Dec 2018 17:24:13 +0200 Subject: [PATCH 12/28] fix(modal): Fix crash if modal is destroyed before dismissed in Android (#6723) --- tns-core-modules/ui/core/view/view.android.ts | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/tns-core-modules/ui/core/view/view.android.ts b/tns-core-modules/ui/core/view/view.android.ts index 66789f729..447430691 100644 --- a/tns-core-modules/ui/core/view/view.android.ts +++ b/tns-core-modules/ui/core/view/view.android.ts @@ -195,8 +195,17 @@ function initializeDialogFragment() { public onDestroy(): void { super.onDestroy(); const owner = this.owner; - owner._isAddedToNativeVisualTree = false; - owner._tearDownUI(true); + + if (owner) { + // Android calls onDestroy before onDismiss. + // Make sure we unload first and then call _tearDownUI. + if (owner.isLoaded) { + owner.callUnloaded(); + } + + owner._isAddedToNativeVisualTree = false; + owner._tearDownUI(true); + } } } @@ -386,7 +395,7 @@ export class View extends ViewCommon { if (!this.nativeViewProtected || !this.hasGestureObservers()) { return; } - + // do not set noop listener that handles the event (disabled listener) if IsUserInteractionEnabled is // false as we might need the ability for the event to pass through to a parent view initializeTouchListener(); From 2b7e7d89e0bb5c3027fc10e163cb54297096cac8 Mon Sep 17 00:00:00 2001 From: Vasil Chimev Date: Thu, 27 Dec 2018 16:44:24 +0200 Subject: [PATCH 13/28] fix-next: undefined root view when reapplying styles (#6729) * fix: undefined root view when reapplying styles Error: ``` JS ERROR TypeError: undefined is not an object (evaluating 'application_1.getRootView()._onCssStateChange') ``` Steps: - `tns run --hmr` - make a change in application styles - restart the application --- tns-core-modules/application/application-common.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tns-core-modules/application/application-common.ts b/tns-core-modules/application/application-common.ts index 3f0d0888c..71af5ddc3 100644 --- a/tns-core-modules/application/application-common.ts +++ b/tns-core-modules/application/application-common.ts @@ -89,8 +89,9 @@ export function livesync(context?: HmrContext) { reapplyAppCss = extensions.some(ext => context.module === fileName.concat(ext)); } - if (reapplyAppCss) { - getRootView()._onCssStateChange(); + const rootView = getRootView(); + if (reapplyAppCss && rootView) { + rootView._onCssStateChange(); } else if (liveSyncCore) { liveSyncCore(); } From 6cdb01d4322521396ba880804fa4fc6dc3a2659a Mon Sep 17 00:00:00 2001 From: Nikolay Tsonev Date: Mon, 31 Dec 2018 14:20:52 +0200 Subject: [PATCH 14/28] set the correct application theme while creating the dialog fragment (#6691) * set the correct application theme while creating the dialog fragment * useing the new approche fusing the new approach for setting the theme only when the modal view is fullscreen(it will break the style when using non-fullscreen modal) * note - get theme change * set the correct application theme while creating the dialog fragment * useing the new approche fusing the new approach for setting the theme only when the modal view is fullscreen(it will break the style when using non-fullscreen modal) * note - get theme change --- tns-core-modules/ui/core/view/view.android.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tns-core-modules/ui/core/view/view.android.ts b/tns-core-modules/ui/core/view/view.android.ts index 447430691..66a3c6f25 100644 --- a/tns-core-modules/ui/core/view/view.android.ts +++ b/tns-core-modules/ui/core/view/view.android.ts @@ -135,8 +135,14 @@ function initializeDialogFragment() { this._shownCallback = options.shownCallback; this.owner._dialogFragment = this; this.setStyle(android.support.v4.app.DialogFragment.STYLE_NO_TITLE, 0); + + let theme = this.getTheme(); + if (this._fullscreen) { + // In fullscreen mode, get the application's theme. + theme = this.getActivity().getApplicationInfo().theme; + } - const dialog = new DialogImpl(this, this.getActivity(), this.getTheme()); + const dialog = new DialogImpl(this, this.getActivity(), theme); // do not override alignment unless fullscreen modal will be shown; // otherwise we might break component-level layout: From 1ae0cfd4b3d72ced8516216566551cf3b1b726b6 Mon Sep 17 00:00:00 2001 From: Manol Donev Date: Wed, 2 Jan 2019 11:17:55 +0200 Subject: [PATCH 15/28] refactor: cleanup unused elements (#6732) --- .../ui/action-bar/action-bar.ios.ts | 1 - tns-core-modules/ui/core/view/view.ios.ts | 1 - tns-core-modules/ui/dialogs/dialogs.ios.ts | 2 +- .../ui/list-view/list-view-common.ts | 2 +- tns-core-modules/ui/list-view/list-view.ios.ts | 2 -- .../ui/scroll-view/scroll-view.ios.ts | 17 ----------------- tns-core-modules/utils/utils.ios.ts | 1 - 7 files changed, 2 insertions(+), 24 deletions(-) diff --git a/tns-core-modules/ui/action-bar/action-bar.ios.ts b/tns-core-modules/ui/action-bar/action-bar.ios.ts index 459a78614..17a96677f 100644 --- a/tns-core-modules/ui/action-bar/action-bar.ios.ts +++ b/tns-core-modules/ui/action-bar/action-bar.ios.ts @@ -6,7 +6,6 @@ import { layout, Color, traceMissingIcon } from "./action-bar-common"; import { fromFileOrResource } from "../../image-source"; import { ios as iosUtils } from "../../utils/utils"; -import { write as traceWrite, categories, messageType } from "../../trace"; export * from "./action-bar-common"; diff --git a/tns-core-modules/ui/core/view/view.ios.ts b/tns-core-modules/ui/core/view/view.ios.ts index 06e62e42d..922b4c61f 100644 --- a/tns-core-modules/ui/core/view/view.ios.ts +++ b/tns-core-modules/ui/core/view/view.ios.ts @@ -1,7 +1,6 @@ // Definitions. import { Point, View as ViewDefinition, dip } from "."; import { ViewBase } from "../view-base"; -import { booleanConverter, Property } from "../view"; import { ViewCommon, layout, isEnabledProperty, originXProperty, originYProperty, automationTextProperty, isUserInteractionEnabledProperty, diff --git a/tns-core-modules/ui/dialogs/dialogs.ios.ts b/tns-core-modules/ui/dialogs/dialogs.ios.ts index 598f49389..91a6cbc5f 100644 --- a/tns-core-modules/ui/dialogs/dialogs.ios.ts +++ b/tns-core-modules/ui/dialogs/dialogs.ios.ts @@ -1,7 +1,7 @@ /** * iOS specific dialogs functions implementation. */ -import { View, ios as iosView } from "../core/view"; +import { ios as iosView } from "../core/view"; import { ConfirmOptions, PromptOptions, PromptResult, LoginOptions, LoginResult, ActionOptions } from "."; import { getCurrentPage, getLabelColor, getButtonColors, getTextFieldColor, isDialogOptions, inputType, capitalizationType, ALERT, OK, CONFIRM, CANCEL, PROMPT, parseLoginOptions } from "./dialogs-common"; import { isString, isDefined, isFunction } from "../../utils/types"; diff --git a/tns-core-modules/ui/list-view/list-view-common.ts b/tns-core-modules/ui/list-view/list-view-common.ts index 746b8527b..9744e0ef4 100644 --- a/tns-core-modules/ui/list-view/list-view-common.ts +++ b/tns-core-modules/ui/list-view/list-view-common.ts @@ -1,5 +1,5 @@ import { ListView as ListViewDefinition, ItemsSource, ItemEventData, TemplatedItemsView } from "."; -import { CoercibleProperty, CssProperty, Style, View, ViewBase, ContainerView, Template, KeyedTemplate, Length, Property, Color, Observable, EventData, CSSType } from "../core/view"; +import { CoercibleProperty, CssProperty, Style, View, ContainerView, Template, KeyedTemplate, Length, Property, Color, Observable, EventData, CSSType } from "../core/view"; import { parse, parseMultipleTemplates } from "../builder"; import { Label } from "../label"; import { ObservableArray, ChangedData } from "../../data/observable-array"; diff --git a/tns-core-modules/ui/list-view/list-view.ios.ts b/tns-core-modules/ui/list-view/list-view.ios.ts index da0b0cb2c..a68067c5f 100644 --- a/tns-core-modules/ui/list-view/list-view.ios.ts +++ b/tns-core-modules/ui/list-view/list-view.ios.ts @@ -7,7 +7,6 @@ import { StackLayout } from "../layouts/stack-layout"; import { ProxyViewContainer } from "../proxy-view-container"; import { profile } from "../../profiling"; import * as trace from "../../trace"; -import { ios as iosUtils } from "../../utils/utils"; export * from "./list-view-common"; @@ -23,7 +22,6 @@ interface ViewItemIndex { } type ItemView = View & ViewItemIndex; -const majorVersion = iosUtils.MajorVersion; class ListViewCell extends UITableViewCell { public static initWithEmptyBackground(): ListViewCell { diff --git a/tns-core-modules/ui/scroll-view/scroll-view.ios.ts b/tns-core-modules/ui/scroll-view/scroll-view.ios.ts index eeade71b8..55a6f4b6b 100644 --- a/tns-core-modules/ui/scroll-view/scroll-view.ios.ts +++ b/tns-core-modules/ui/scroll-view/scroll-view.ios.ts @@ -3,9 +3,6 @@ import { View, layout, ScrollViewBase, scrollBarIndicatorVisibleProperty, isScrollEnabledProperty } from "./scroll-view-common"; import { ios as iosUtils } from "../../utils/utils"; -// HACK: Webpack. Use a fully-qualified import to allow resolve.extensions(.ios.js) to -// kick in. `../utils` doesn't seem to trigger the webpack extensions mechanism. -import * as uiUtils from "tns-core-modules/ui/utils"; export * from "./scroll-view-common"; @@ -193,18 +190,4 @@ export class ScrollView extends ScrollViewBase { } } -function getTabBarHeight(scrollView: ScrollView): number { - let parent = scrollView.parent; - while (parent) { - const controller = parent.viewController; - if (controller instanceof UITabBarController) { - return uiUtils.ios.getActualHeight(controller.tabBar); - } - - parent = parent.parent; - } - - return 0; -} - ScrollView.prototype.recycleNativeView = "auto"; diff --git a/tns-core-modules/utils/utils.ios.ts b/tns-core-modules/utils/utils.ios.ts index 77da535b7..8665fb40d 100644 --- a/tns-core-modules/utils/utils.ios.ts +++ b/tns-core-modules/utils/utils.ios.ts @@ -127,7 +127,6 @@ export module ios { } if (rootViewController.isKindOfClass(UITabBarController.class())) { - let selectedTab = (rootViewController).selectedViewController; return getVisibleViewController(rootViewController); } From 984f162c1c4284d90118e00b8b3cc2c5a70b1ba8 Mon Sep 17 00:00:00 2001 From: Alexander Djenkov Date: Fri, 4 Jan 2019 16:57:26 +0200 Subject: [PATCH 16/28] fix(tab-view): remove onBackPressed override (#6755) --- tns-core-modules/ui/tab-view/tab-view.android.ts | 9 --------- 1 file changed, 9 deletions(-) diff --git a/tns-core-modules/ui/tab-view/tab-view.android.ts b/tns-core-modules/ui/tab-view/tab-view.android.ts index 6c2302e63..fb214f74e 100644 --- a/tns-core-modules/ui/tab-view/tab-view.android.ts +++ b/tns-core-modules/ui/tab-view/tab-view.android.ts @@ -545,15 +545,6 @@ export class TabView extends TabViewBase { super.disposeNativeView(); } - public onBackPressed(): boolean { - const currentView = this._selectedView; - if (currentView) { - return currentView.onBackPressed(); - } - - return false; - } - public _onRootViewReset(): void { super._onRootViewReset(); From 37f5359fc59abf3267575be581816f763b6d7d70 Mon Sep 17 00:00:00 2001 From: Emil Tabakov Date: Mon, 7 Jan 2019 15:12:05 +0200 Subject: [PATCH 17/28] chore: update community files (#6763) --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index 9d63a0a67..061c44028 100755 --- a/LICENSE +++ b/LICENSE @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright (c) 2015-2018 Progress Software Corporation + Copyright (c) 2015-2019 Progress Software Corporation Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. From 35ebe8b91d4549f515487cbff80eff5c73b904df Mon Sep 17 00:00:00 2001 From: Emil Tabakov Date: Mon, 7 Jan 2019 15:17:15 +0200 Subject: [PATCH 18/28] chore: update LICENSE for tns-core-modules (#6761) --- tns-core-modules/LICENSE | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tns-core-modules/LICENSE b/tns-core-modules/LICENSE index 1c24a9142..ef8add3b4 100755 --- a/tns-core-modules/LICENSE +++ b/tns-core-modules/LICENSE @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright (c) 2015-2018 Telerik AD + Copyright (c) 2015-2019 Progress Software Corporation Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -198,4 +198,4 @@ distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and - limitations under the License. \ No newline at end of file + limitations under the License. From 2085d1e4acffe187a23d436a332060b7b5cf11f6 Mon Sep 17 00:00:00 2001 From: Alexander Djenkov Date: Tue, 8 Jan 2019 13:48:47 +0200 Subject: [PATCH 19/28] fix(list-view-android): app crashes on ListView item template change (#6634) * fix(list-view): app crashes on first ListView item template change * tests: add tests for changing ListView item template with expression --- .../list-view/dynamic-templates.ts | 21 +++++++++++++++++++ .../list-view/dynamic-templates.xml | 14 +++++++++++++ apps/app/ui-tests-app/list-view/main-page.ts | 1 + .../ui-tests-app/list-view/main-view-model.ts | 17 +++++++++++++-- .../ui/list-view/list-view-common.ts | 5 +++++ 5 files changed, 56 insertions(+), 2 deletions(-) create mode 100644 apps/app/ui-tests-app/list-view/dynamic-templates.ts create mode 100644 apps/app/ui-tests-app/list-view/dynamic-templates.xml diff --git a/apps/app/ui-tests-app/list-view/dynamic-templates.ts b/apps/app/ui-tests-app/list-view/dynamic-templates.ts new file mode 100644 index 000000000..06e973c1d --- /dev/null +++ b/apps/app/ui-tests-app/list-view/dynamic-templates.ts @@ -0,0 +1,21 @@ +import { Page } from "tns-core-modules/ui/page"; +import { ViewModel } from "./main-view-model"; + +export function pageLoaded(args) { + let page = args.object; + const viewModel = new ViewModel(); + + page.bindingContext = { + "items": viewModel.items + } +} + +exports.onItemTap = function (args) { + const list = args.object; + let index = args.index; + let listArray = list.page.bindingContext["items"]; + let currentItem = listArray.getItem(index); + + currentItem.age = currentItem.age + 1; + listArray.setItem(index, currentItem); +} \ No newline at end of file diff --git a/apps/app/ui-tests-app/list-view/dynamic-templates.xml b/apps/app/ui-tests-app/list-view/dynamic-templates.xml new file mode 100644 index 000000000..bca89ebe9 --- /dev/null +++ b/apps/app/ui-tests-app/list-view/dynamic-templates.xml @@ -0,0 +1,14 @@ + + + + + + + + + + \ No newline at end of file diff --git a/apps/app/ui-tests-app/list-view/main-page.ts b/apps/app/ui-tests-app/list-view/main-page.ts index 2265aec8d..4b7b3e59f 100644 --- a/apps/app/ui-tests-app/list-view/main-page.ts +++ b/apps/app/ui-tests-app/list-view/main-page.ts @@ -13,6 +13,7 @@ export function loadExamples() { const examples = new Map(); examples.set("list-view-templates", "list-view/list-view"); examples.set("images-template", "list-view/images-template"); + examples.set("dynamic-templates", "list-view/dynamic-templates"); examples.set("bindings", "list-view/listview-binding"); examples.set("listview-bg-separator-color", "list-view/listview-bg-separator-color"); examples.set("csslv", "list-view/csslv"); diff --git a/apps/app/ui-tests-app/list-view/main-view-model.ts b/apps/app/ui-tests-app/list-view/main-view-model.ts index 18e6d6866..9ae9bcf14 100644 --- a/apps/app/ui-tests-app/list-view/main-view-model.ts +++ b/apps/app/ui-tests-app/list-view/main-view-model.ts @@ -4,11 +4,13 @@ import { ObservableArray } from "tns-core-modules/data/observable-array"; export class Item extends Observable { private _name: string; private _id: number; + private _age: number; - constructor(name: string, id: number) { + constructor(name: string, id: number, age: number) { super(); this._name = name; this._id = id; + this._age = age; } get name(): string { @@ -33,6 +35,17 @@ export class Item extends Observable { } } + get age(): number { + return this._age; + } + + set age(value: number) { + if (this._age !== value) { + this._age = value; + this.notifyPropertyChange("age", value) + } + } + public toString() { return `${this.name} ${this.id}`; } @@ -44,7 +57,7 @@ export class ViewModel extends Observable { get items(): ObservableArray { this._items = new ObservableArray(); for (let i = 0; i < 100; i++) { - this._items.push(new Item(`Item`, i)); + this._items.push(new Item(`Item`, i, 0)); } return this._items; } diff --git a/tns-core-modules/ui/list-view/list-view-common.ts b/tns-core-modules/ui/list-view/list-view-common.ts index 9744e0ef4..5b0cf65c3 100644 --- a/tns-core-modules/ui/list-view/list-view-common.ts +++ b/tns-core-modules/ui/list-view/list-view-common.ts @@ -66,6 +66,11 @@ export abstract class ListViewBase extends ContainerView implements ListViewDefi }); this._itemTemplateSelector = (item: any, index: number, items: any) => { item["$index"] = index; + + if (this._itemTemplateSelectorBindable.bindingContext === item) { + this._itemTemplateSelectorBindable.bindingContext = null; + } + this._itemTemplateSelectorBindable.bindingContext = item; return this._itemTemplateSelectorBindable.get("templateKey"); }; From 42c25370ee79731d83f5f5094c59a662ac5b6ba6 Mon Sep 17 00:00:00 2001 From: Svetoslav Date: Tue, 8 Jan 2019 13:55:50 +0200 Subject: [PATCH 20/28] chore: merge release in master (#6731) * Fix some lint errors * release: cut the 5.1.1 release * chore: bump widgets version to 5.1.2 --- CHANGELOG.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8a3ad5f42..48871fdee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,21 @@ + +## [5.1.1](https://github.com/NativeScript/NativeScript/compare/5.1.0...5.1.1) (2018-12-19) + + +### Bug Fixes + +* **android:** animator restore logic on simulated nav ([#6710](https://github.com/NativeScript/NativeScript/issues/6710)) ([54b6df6](https://github.com/NativeScript/NativeScript/commit/54b6df6)) +* **android:** failure saving state in mixed parent/nested frame nav ([#6719](https://github.com/NativeScript/NativeScript/issues/6719)) ([e5f110f](https://github.com/NativeScript/NativeScript/commit/e5f110f)) +* **android:** nested fragment disappears on parent fragment removal ([#6677](https://github.com/NativeScript/NativeScript/issues/6677)) ([c084660](https://github.com/NativeScript/NativeScript/commit/c084660)) + + +### Features + +* **tns-platform-declarations:** Generate iOS typings from iOS 12.1 SDK ([#6693](https://github.com/NativeScript/NativeScript/issues/6693)) ([1c0218e](https://github.com/NativeScript/NativeScript/commit/1c0218e)) +* **view:** added iOS parameter for modal presentation style ([#6409](https://github.com/NativeScript/NativeScript/issues/6409)) ([540b2b4](https://github.com/NativeScript/NativeScript/commit/540b2b4)) + + + # [5.1.0](https://github.com/NativeScript/NativeScript/compare/5.0.5...5.1.0) (2018-12-05) From 46c9de020ea5959d1a02e75b6836fd0a08b7e9f0 Mon Sep 17 00:00:00 2001 From: Manol Donev Date: Tue, 8 Jan 2019 15:20:11 +0200 Subject: [PATCH 21/28] fix(android): raise resume event on activity.onPostResume() (#6766) --- .../application/application.android.ts | 7 +---- tns-core-modules/ui/frame/activity.android.ts | 4 +++ tns-core-modules/ui/frame/frame.android.ts | 28 +++++++++++++++++-- tns-core-modules/ui/frame/frame.d.ts | 1 + 4 files changed, 32 insertions(+), 8 deletions(-) diff --git a/tns-core-modules/application/application.android.ts b/tns-core-modules/application/application.android.ts index 6d5166675..e27378534 100644 --- a/tns-core-modules/application/application.android.ts +++ b/tns-core-modules/application/application.android.ts @@ -290,15 +290,10 @@ function initLifecycleCallbacks() { onActivityResumed: profile("onActivityResumed", function (activity: android.support.v7.app.AppCompatActivity) { androidApp.foregroundActivity = activity; - if ((activity).isNativeScriptActivity) { - notify({ eventName: resumeEvent, object: androidApp, android: activity }); - androidApp.paused = false; - } - androidApp.notify({ eventName: ActivityResumed, object: androidApp, activity: activity }); }), - onActivitySaveInstanceState: profile("onActivityResumed", function (activity: android.support.v7.app.AppCompatActivity, outState: android.os.Bundle) { + onActivitySaveInstanceState: profile("onActivitySaveInstanceState", function (activity: android.support.v7.app.AppCompatActivity, outState: android.os.Bundle) { androidApp.notify({ eventName: SaveActivityState, object: androidApp, activity: activity, bundle: outState }); }), diff --git a/tns-core-modules/ui/frame/activity.android.ts b/tns-core-modules/ui/frame/activity.android.ts index 55d9118a9..946ca63df 100644 --- a/tns-core-modules/ui/frame/activity.android.ts +++ b/tns-core-modules/ui/frame/activity.android.ts @@ -50,6 +50,10 @@ class NativeScriptActivity extends android.support.v7.app.AppCompatActivity { this._callbacks.onDestroy(this, super.onDestroy); } + public onPostResume(): void { + this._callbacks.onPostResume(this, super.onPostResume); + } + public onBackPressed(): void { this._callbacks.onBackPressed(this, super.onBackPressed); } diff --git a/tns-core-modules/ui/frame/frame.android.ts b/tns-core-modules/ui/frame/frame.android.ts index d2e3c9943..4053b9890 100644 --- a/tns-core-modules/ui/frame/frame.android.ts +++ b/tns-core-modules/ui/frame/frame.android.ts @@ -859,13 +859,13 @@ class FragmentCallbacksImplementation implements AndroidFragmentCallbacks { // lose its parent we temporarily add it to the parent, and then remove it (addViewInLayout doesn't trigger layout pass) const nativeView = page.nativeViewProtected; if (nativeView != null) { - const parentView = nativeView.getParent(); + const parentView = nativeView.getParent(); if (parentView instanceof android.view.ViewGroup) { if (parentView.getChildCount() === 0) { parentView.addViewInLayout(nativeView, -1, new org.nativescript.widgets.CommonLayoutParams()); } - parentView.removeView(nativeView); + parentView.removeView(nativeView); } } @@ -1006,6 +1006,30 @@ class ActivityCallbacksImplementation implements AndroidActivityCallbacks { } } + @profile + public onPostResume(activity: any, superFunc: Function): void { + superFunc.call(activity); + + if (traceEnabled()) { + traceWrite("NativeScriptActivity.onPostResume();", traceCategories.NativeLifecycle); + } + + // NOTE: activity.onPostResume() is called when activity resume is complete and we can + // safely raise the application resume event; + // onActivityResumed(...) lifecycle callback registered in application is called too early + // and raising the application resume event there causes issues like + // https://github.com/NativeScript/NativeScript/issues/6708 + if ((activity).isNativeScriptActivity) { + const args = { + eventName: application.resumeEvent, + object: application.android, + android: activity + }; + application.notify(args); + application.android.paused = false; + } + } + @profile public onDestroy(activity: any, superFunc: Function): void { if (traceEnabled()) { diff --git a/tns-core-modules/ui/frame/frame.d.ts b/tns-core-modules/ui/frame/frame.d.ts index dac7f0f55..a92519b69 100644 --- a/tns-core-modules/ui/frame/frame.d.ts +++ b/tns-core-modules/ui/frame/frame.d.ts @@ -415,6 +415,7 @@ export interface AndroidActivityCallbacks { onSaveInstanceState(activity: any, outState: any, superFunc: Function): void; onStart(activity: any, superFunc: Function): void; onStop(activity: any, superFunc: Function): void; + onPostResume(activity: any, superFunc: Function): void; onDestroy(activity: any, superFunc: Function): void; onBackPressed(activity: any, superFunc: Function): void; onRequestPermissionsResult(activity: any, requestCode: number, permissions: Array, grantResults: Array, superFunc: Function): void; From a6d561e5499779fe74132682dc63744b3627afb2 Mon Sep 17 00:00:00 2001 From: Manol Donev Date: Tue, 8 Jan 2019 15:23:35 +0200 Subject: [PATCH 22/28] refactor: update e2e tests for CI (#6722) --- e2e/config/mocha.opts | 2 +- .../app/frame-root/frame-home-page.ts | 4 +- .../frame-multi-home-page.ts} | 4 +- .../app/frame-root/frame-multi-home-page.xml | 2 +- .../app/home/home-page.ts | 8 +-- .../app/home/home-page.xml | 4 +- ...out-root-frame.ts => layout-frame-root.ts} | 0 ...t-root-frame.xml => layout-frame-root.xml} | 0 .../app/layout-root/layout-home-page.ts | 4 +- .../layout-root/layout-home-secondary-page.ts | 4 +- .../layout-multi-frame-root.ts} | 0 ...-frame.xml => layout-multi-frame-root.xml} | 2 +- .../app/players/players-items-page.ts | 4 +- .../app/tab-page/tabs-bottom-page.ts | 46 ++++++++++++ .../app/tab-page/tabs-bottom-page.xml | 2 +- .../app/tab-page/tabs-top-page.ts | 46 ++++++++++++ ...top-page.android.xml => tabs-top-page.xml} | 26 +++---- .../app/tab-root/tab-bottom-root.ts | 5 ++ ...ab-root-bottom.xml => tab-bottom-root.xml} | 2 +- .../app/tab-root/tab-top-root.ts | 5 ++ ...-root-top.android.xml => tab-top-root.xml} | 2 +- .../app/teams/teams-items-page.ts | 4 +- e2e/nested-frame-navigation/e2e/config.ts | 3 +- .../e2e/frame-root.e2e-spec.ts | 44 ++++++++++-- .../e2e/frame-tab-root.e2e-spec.ts | 30 ++++++-- .../e2e/layout-root.e2e-spec.ts | 70 ++++++++++++++++--- e2e/nested-frame-navigation/e2e/screen.ts | 24 +++---- .../e2e/shared.e2e-spec.ts | 17 ++++- .../e2e/tab-root.e2e-spec.ts | 4 ++ 29 files changed, 295 insertions(+), 73 deletions(-) rename e2e/nested-frame-navigation/app/{tab-page/tabs-page.ts => frame-root/frame-multi-home-page.ts} (95%) rename e2e/nested-frame-navigation/app/layout-root/{layout-root-frame.ts => layout-frame-root.ts} (100%) rename e2e/nested-frame-navigation/app/layout-root/{layout-root-frame.xml => layout-frame-root.xml} (100%) rename e2e/nested-frame-navigation/app/{tab-root/tab-root.ts => layout-root/layout-multi-frame-root.ts} (100%) rename e2e/nested-frame-navigation/app/layout-root/{layout-root-multi-frame.xml => layout-multi-frame-root.xml} (75%) create mode 100644 e2e/nested-frame-navigation/app/tab-page/tabs-bottom-page.ts create mode 100644 e2e/nested-frame-navigation/app/tab-page/tabs-top-page.ts rename e2e/nested-frame-navigation/app/tab-page/{tabs-top-page.android.xml => tabs-top-page.xml} (53%) create mode 100644 e2e/nested-frame-navigation/app/tab-root/tab-bottom-root.ts rename e2e/nested-frame-navigation/app/tab-root/{tab-root-bottom.xml => tab-bottom-root.xml} (91%) create mode 100644 e2e/nested-frame-navigation/app/tab-root/tab-top-root.ts rename e2e/nested-frame-navigation/app/tab-root/{tab-root-top.android.xml => tab-top-root.xml} (90%) diff --git a/e2e/config/mocha.opts b/e2e/config/mocha.opts index 796ec4724..a10a923f7 100644 --- a/e2e/config/mocha.opts +++ b/e2e/config/mocha.opts @@ -1,4 +1,4 @@ ---timeout 80000 +--timeout 300000 --recursive e2e --reporter mocha-multi --reporter-options spec=-,mocha-junit-reporter=test-results.xml \ No newline at end of file diff --git a/e2e/nested-frame-navigation/app/frame-root/frame-home-page.ts b/e2e/nested-frame-navigation/app/frame-root/frame-home-page.ts index 563f6f73d..95859bef6 100644 --- a/e2e/nested-frame-navigation/app/frame-root/frame-home-page.ts +++ b/e2e/nested-frame-navigation/app/frame-root/frame-home-page.ts @@ -21,7 +21,7 @@ export function onNavigateSlide(args: EventData) { animated: true, transition: { name: "slide", - duration: 380, + duration: 300, curve: "easeIn" } }); @@ -34,7 +34,7 @@ export function onNavigateFlip(args: EventData) { animated: true, transition: { name: "flip", - duration: 380, + duration: 300, curve: "easeIn" } }); diff --git a/e2e/nested-frame-navigation/app/tab-page/tabs-page.ts b/e2e/nested-frame-navigation/app/frame-root/frame-multi-home-page.ts similarity index 95% rename from e2e/nested-frame-navigation/app/tab-page/tabs-page.ts rename to e2e/nested-frame-navigation/app/frame-root/frame-multi-home-page.ts index 563f6f73d..95859bef6 100644 --- a/e2e/nested-frame-navigation/app/tab-page/tabs-page.ts +++ b/e2e/nested-frame-navigation/app/frame-root/frame-multi-home-page.ts @@ -21,7 +21,7 @@ export function onNavigateSlide(args: EventData) { animated: true, transition: { name: "slide", - duration: 380, + duration: 300, curve: "easeIn" } }); @@ -34,7 +34,7 @@ export function onNavigateFlip(args: EventData) { animated: true, transition: { name: "flip", - duration: 380, + duration: 300, curve: "easeIn" } }); diff --git a/e2e/nested-frame-navigation/app/frame-root/frame-multi-home-page.xml b/e2e/nested-frame-navigation/app/frame-root/frame-multi-home-page.xml index 88d9c1371..c65c41a05 100644 --- a/e2e/nested-frame-navigation/app/frame-root/frame-multi-home-page.xml +++ b/e2e/nested-frame-navigation/app/frame-root/frame-multi-home-page.xml @@ -1,4 +1,4 @@ - + diff --git a/e2e/nested-frame-navigation/app/home/home-page.ts b/e2e/nested-frame-navigation/app/home/home-page.ts index 5cac9f426..af70f5a08 100644 --- a/e2e/nested-frame-navigation/app/home/home-page.ts +++ b/e2e/nested-frame-navigation/app/home/home-page.ts @@ -3,11 +3,11 @@ import { EventData } from "tns-core-modules/ui/core/view"; import { Button } from "tns-core-modules/ui/button"; export function onNavigateToLayoutFrame(args: EventData) { - application._resetRootView({ moduleName: "layout-root/layout-root-frame" }); + application._resetRootView({ moduleName: "layout-root/layout-frame-root" }); } export function onNavigateToLayoutMultiFrame(args: EventData) { - application._resetRootView({ moduleName: "layout-root/layout-root-multi-frame" }); + application._resetRootView({ moduleName: "layout-root/layout-multi-frame-root" }); } export function onNavigateToPageFrame(args: EventData) { @@ -31,9 +31,9 @@ export function onNavigateToTabsBottomPage(args: EventData) { } export function onNavigateToTabsTopRoot(args: EventData) { - application._resetRootView({ moduleName: "tab-root/tab-root-top" }); + application._resetRootView({ moduleName: "tab-root/tab-top-root" }); } export function onNavigateToTabsBottomRoot(args: EventData) { - application._resetRootView({ moduleName: "tab-root/tab-root-bottom" }); + application._resetRootView({ moduleName: "tab-root/tab-bottom-root" }); } diff --git a/e2e/nested-frame-navigation/app/home/home-page.xml b/e2e/nested-frame-navigation/app/home/home-page.xml index 229af254b..54367f44a 100644 --- a/e2e/nested-frame-navigation/app/home/home-page.xml +++ b/e2e/nested-frame-navigation/app/home/home-page.xml @@ -10,9 +10,9 @@