diff --git a/CHANGELOG.md b/CHANGELOG.md
index e6a659ae6..0537ba975 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,30 @@
+
+# [5.4.0](https://github.com/NativeScript/NativeScript/compare/5.3.2...5.4.0) (2019-05-14)
+
+
+### Bug Fixes
+
+* throw if failed to load component ([#7186](https://github.com/NativeScript/NativeScript/issues/7186)) ([b7abb3d](https://github.com/NativeScript/NativeScript/commit/b7abb3d))
+* **android/button:** possible incorrect button visual state ([#7190](https://github.com/NativeScript/NativeScript/issues/7190)) ([2a02360](https://github.com/NativeScript/NativeScript/commit/2a02360))
+* **devtools-ios:** Ensure UI modifications run on main thread ([c60f74d](https://github.com/NativeScript/NativeScript/commit/c60f74d)), closes [#7219](https://github.com/NativeScript/NativeScript/issues/7219)
+* **ios:** add null check to TouchGestureRecognizer ([#7182](https://github.com/NativeScript/NativeScript/issues/7182)) ([7d3f0d9](https://github.com/NativeScript/NativeScript/commit/7d3f0d9))
+* **ios:** application.displayedEvent does not depend on trace to fire ([#7141](https://github.com/NativeScript/NativeScript/issues/7141)) ([#7156](https://github.com/NativeScript/NativeScript/issues/7156)) ([4e56c89](https://github.com/NativeScript/NativeScript/commit/4e56c89))
+* **ios:** image cache module not longer sets null in NSCache ([#7171](https://github.com/NativeScript/NativeScript/issues/7171)) ([4f79d2e](https://github.com/NativeScript/NativeScript/commit/4f79d2e))
+* **ios-modal:** closeCallback not being called with popover presentation style ([#7189](https://github.com/NativeScript/NativeScript/issues/7189)) ([aa44eb9](https://github.com/NativeScript/NativeScript/commit/aa44eb9))
+* **ios-tabview:** crash when setting tab text color ([#7188](https://github.com/NativeScript/NativeScript/issues/7188)) ([77c45da](https://github.com/NativeScript/NativeScript/commit/77c45da))
+* **text:** crash when removing FormattedText ([#7237](https://github.com/NativeScript/NativeScript/issues/7237)) ([37b53c6](https://github.com/NativeScript/NativeScript/commit/37b53c6))
+
+
+### Features
+
+* **android:** elevation shadow support ([#7136](https://github.com/NativeScript/NativeScript/issues/7136)) ([cf533a7](https://github.com/NativeScript/NativeScript/commit/cf533a7))
+* **android:** implement a 'activityNewIntent' event ([3efc06e](https://github.com/NativeScript/NativeScript/commit/3efc06e))
+* **android:** implement BorderDrawable outline ([ec07a99](https://github.com/NativeScript/NativeScript/commit/ec07a99))
+* **hmr:** preserve navigation history on applying changes ([#7146](https://github.com/NativeScript/NativeScript/issues/7146)) ([d35e14e](https://github.com/NativeScript/NativeScript/commit/d35e14e))
+* **switch:** add property for off state background color ([#7138](https://github.com/NativeScript/NativeScript/issues/7138)) ([f0146f0](https://github.com/NativeScript/NativeScript/commit/f0146f0))
+
+
+
## [5.3.2](https://github.com/NativeScript/NativeScript/compare/5.3.1...5.3.2) (2019-05-03)
diff --git a/apps/app/ui-tests-app/button/button-border.css b/apps/app/ui-tests-app/button/button-border.css
index 3b404e027..9f01234a7 100644
--- a/apps/app/ui-tests-app/button/button-border.css
+++ b/apps/app/ui-tests-app/button/button-border.css
@@ -46,7 +46,7 @@ Button {
}
#s10 {
- border-width: 5 0; border-color: black; background-color: white;
+ android-elevation: 0; border-width: 5 0; border-color: black;
}
#s11 {
diff --git a/apps/app/ui-tests-app/css/elevation.css b/apps/app/ui-tests-app/css/elevation.css
new file mode 100644
index 000000000..5ebb8a2ab
--- /dev/null
+++ b/apps/app/ui-tests-app/css/elevation.css
@@ -0,0 +1,43 @@
+Label, Button {
+ text-align: center;
+ padding: 10;
+ margin: 16;
+ background-color: #bbb;
+}
+
+.elevation-0 {
+ android-elevation: 0;
+}
+
+.elevation-2 {
+ android-elevation: 2;
+}
+
+.elevation-4 {
+ android-elevation: 4;
+}
+
+.elevation-4:highlighted {
+ android-elevation: 2;
+}
+
+.elevation-8 {
+ android-elevation: 8;
+}
+
+.elevation-10 {
+ android-elevation: 10;
+}
+
+.pressed-z-10 {
+ android-dynamic-elevation-offset: 10;
+}
+
+.round {
+ color: #fff;
+ background-color: #ff1744;
+ border-radius: 50%; /* TODO kills elevation */
+ width: 80;
+ height: 80;
+ android-elevation: 8;
+}
\ No newline at end of file
diff --git a/apps/app/ui-tests-app/css/elevation.ts b/apps/app/ui-tests-app/css/elevation.ts
new file mode 100644
index 000000000..dd7e54701
--- /dev/null
+++ b/apps/app/ui-tests-app/css/elevation.ts
@@ -0,0 +1,20 @@
+import { Button } from "tns-core-modules/ui/button/button";
+import { EventData } from "tns-core-modules/ui/page/page";
+
+const states = [
+ { class: "", text: "default elevation" },
+ { class: "elevation-10", text: "elevetion 10" },
+ { class: "elevation-10 pressed-z-10", text: "elevetion 10 pressed-z 10" },
+ { class: "elevation-0", text: "elevetion 0" },
+]
+let currentState = 0;
+
+export function buttonTap(args: EventData) {
+ let btn: Button = args.object as Button;
+ currentState++;
+ if (currentState >= states.length) {
+ currentState = 0;
+ }
+ btn.className = states[currentState].class;
+ btn.text = states[currentState].text;
+}
\ No newline at end of file
diff --git a/apps/app/ui-tests-app/css/elevation.xml b/apps/app/ui-tests-app/css/elevation.xml
new file mode 100644
index 000000000..37a492e92
--- /dev/null
+++ b/apps/app/ui-tests-app/css/elevation.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/apps/app/ui-tests-app/css/main-page.ts b/apps/app/ui-tests-app/css/main-page.ts
index 464da8189..c892c71ea 100644
--- a/apps/app/ui-tests-app/css/main-page.ts
+++ b/apps/app/ui-tests-app/css/main-page.ts
@@ -38,6 +38,7 @@ export function loadExamples() {
examples.set("margins-paddings-with-percentage", "css/margins-paddings-with-percentage");
examples.set("padding-and-border", "css/padding-and-border");
examples.set("combinators", "css/combinators");
+ examples.set("elevation", "css/elevation");
examples.set("styled-formatted-text", "css/styled-formatted-text");
examples.set("non-uniform-radius", "css/non-uniform-radius");
examples.set("missing-background-image", "css/missing-background-image");
diff --git a/apps/app/ui-tests-app/css/pixels.xml b/apps/app/ui-tests-app/css/pixels.xml
index 30f25d526..bf3c19849 100644
--- a/apps/app/ui-tests-app/css/pixels.xml
+++ b/apps/app/ui-tests-app/css/pixels.xml
@@ -4,7 +4,7 @@
-
+
@@ -12,7 +12,7 @@
-
+
@@ -32,7 +32,7 @@
-
+
@@ -40,7 +40,7 @@
-
+
diff --git a/apps/app/ui-tests-app/flexbox/flexbox.css b/apps/app/ui-tests-app/flexbox/flexbox.css
index 9f2bc32fc..022add17e 100644
--- a/apps/app/ui-tests-app/flexbox/flexbox.css
+++ b/apps/app/ui-tests-app/flexbox/flexbox.css
@@ -20,9 +20,9 @@
border-color: gray;
}
.control Button {
+ android-elevation: 0;
border-width: 1 1 0 0;
border-color: gray;
- background-color: white;
font-size: 9;
padding: 0;
height: 0;
diff --git a/apps/app/ui-tests-app/issues/issue-3113.css b/apps/app/ui-tests-app/issues/issue-3113.css
index 3a3cab238..80d625121 100644
--- a/apps/app/ui-tests-app/issues/issue-3113.css
+++ b/apps/app/ui-tests-app/issues/issue-3113.css
@@ -1,16 +1,16 @@
#button1 {
- border-color: transparent;
+ android-elevation: 0;
+ border-color: rgba(0, 0, 0, 0);
border-width: 3;
- background-color: white;
}
#button2 {
+ android-elevation: 0;
border-color: rgba(0, 0, 0, 0.5);
border-width: 3;
- background-color: white;
}
#button3 {
+ android-elevation: 0;
border-width: 3;
- background-color: white;
}
\ No newline at end of file
diff --git a/apps/app/ui-tests-app/tab-view/main-page.ts b/apps/app/ui-tests-app/tab-view/main-page.ts
index 69d4aa857..50f8dca5d 100644
--- a/apps/app/ui-tests-app/tab-view/main-page.ts
+++ b/apps/app/ui-tests-app/tab-view/main-page.ts
@@ -27,5 +27,6 @@ export function loadExamples() {
examples.set("tab-view-tab-text-font-size", "tab-view/tab-view-tab-text-font-size");
examples.set("tab-view-android-swipe", "tab-view/tab-view-android-swipe");
examples.set("tab-view-icon-title-placement", "tab-view/icon-title-placement");
+ examples.set("tab-text-color", "tab-view/tab-text-color");
return examples;
}
diff --git a/apps/app/ui-tests-app/tab-view/tab-text-color.xml b/apps/app/ui-tests-app/tab-view/tab-text-color.xml
new file mode 100644
index 000000000..8f851e60d
--- /dev/null
+++ b/apps/app/ui-tests-app/tab-view/tab-text-color.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/e2e/animation/package.json b/e2e/animation/package.json
index 00c40a851..b89e6fd59 100644
--- a/e2e/animation/package.json
+++ b/e2e/animation/package.json
@@ -19,7 +19,6 @@
"devDependencies": {
"@types/chai": "~4.1.7",
"@types/mocha": "~5.2.5",
- "@types/node": "~10.12.18",
"babel-traverse": "6.26.0",
"babel-types": "6.26.0",
"babylon": "6.18.0",
diff --git a/e2e/modal-navigation/app/home/home-page.ts b/e2e/modal-navigation/app/home/home-page.ts
index 54cb458fa..1ce7f9179 100644
--- a/e2e/modal-navigation/app/home/home-page.ts
+++ b/e2e/modal-navigation/app/home/home-page.ts
@@ -1,7 +1,7 @@
import * as application from "tns-core-modules/application";
import { StackLayout } from "tns-core-modules/ui/layouts/stack-layout";
import { NavigatedData, Page } from "tns-core-modules/ui/page";
-import { View, EventData } from "tns-core-modules/ui/core/view";
+import { View, EventData, ShowModalOptions } from "tns-core-modules/ui/core/view";
import { Frame } from "tns-core-modules/ui/frame";
export function onNavigatingTo(args: NavigatedData) {
@@ -29,6 +29,20 @@ export function onModalNoPage(args: EventData) {
false);
}
+export function onPopoverModal(args: EventData) {
+ const view = args.object as View;
+ let options: ShowModalOptions = {
+ context: "context",
+ closeCallback: () => console.log("home-page modal popover frame closed"),
+ animated: false,
+ ios: {
+ presentationStyle: UIModalPresentationStyle.Popover
+ }
+ }
+
+ view.showModal("modal-no-page/modal-no-page", options);
+}
+
export function onModalFrame(args: EventData) {
const view = args.object as View;
diff --git a/e2e/modal-navigation/app/home/home-page.xml b/e2e/modal-navigation/app/home/home-page.xml
index 67a6197eb..62bfbc778 100644
--- a/e2e/modal-navigation/app/home/home-page.xml
+++ b/e2e/modal-navigation/app/home/home-page.xml
@@ -20,6 +20,7 @@
+
diff --git a/e2e/modal-navigation/app/modal-no-page/modal-no-page.ts b/e2e/modal-navigation/app/modal-no-page/modal-no-page.ts
index 88395c2b7..2652b50bd 100644
--- a/e2e/modal-navigation/app/modal-no-page/modal-no-page.ts
+++ b/e2e/modal-navigation/app/modal-no-page/modal-no-page.ts
@@ -3,7 +3,7 @@ import { NavigatedData, Page } from "tns-core-modules/ui/page";
import { View, EventData } from "tns-core-modules/ui/core/view";
import { Frame, ShownModallyData } from "tns-core-modules/ui/frame";
import { fromObject } from "tns-core-modules/data/observable";
-import { confirm } from "ui/dialogs";
+import { confirm } from "tns-core-modules/ui/dialogs";
export function onLoaded(args) {
console.log("modal-no-page loaded");
diff --git a/e2e/modal-navigation/app/modal/modal-page.ts b/e2e/modal-navigation/app/modal/modal-page.ts
index c191dfe95..6de08686d 100644
--- a/e2e/modal-navigation/app/modal/modal-page.ts
+++ b/e2e/modal-navigation/app/modal/modal-page.ts
@@ -3,7 +3,7 @@ import { NavigatedData, Page } from "tns-core-modules/ui/page";
import { View, EventData } from "tns-core-modules/ui/core/view";
import { Frame, ShownModallyData } from "tns-core-modules/ui/frame";
import { fromObject } from "tns-core-modules/data/observable";
-import { confirm } from "ui/dialogs";
+import { confirm } from "tns-core-modules/ui/dialogs";
export function onShowingModally(args: ShownModallyData) {
console.log("modal-page showingModally");
diff --git a/e2e/modal-navigation/package.json b/e2e/modal-navigation/package.json
index 68db87859..b9fca7282 100644
--- a/e2e/modal-navigation/package.json
+++ b/e2e/modal-navigation/package.json
@@ -19,13 +19,13 @@
"devDependencies": {
"@types/chai": "~4.1.7",
"@types/mocha": "~5.2.5",
- "@types/node": "^7.0.5",
"mocha": "~5.2.0",
"mochawesome": "~3.1.2",
"nativescript-dev-appium": "next",
"nativescript-dev-typescript": "next",
"nativescript-dev-webpack": "next",
"rimraf": "^2.6.2",
+ "tns-platform-declarations": "next",
"typescript": "^3.1.6"
},
"scripts": {
diff --git a/e2e/modal-navigation/references.d.ts b/e2e/modal-navigation/references.d.ts
new file mode 100644
index 000000000..b945d69c5
--- /dev/null
+++ b/e2e/modal-navigation/references.d.ts
@@ -0,0 +1 @@
+///
\ No newline at end of file
diff --git a/e2e/nested-frame-navigation/package.json b/e2e/nested-frame-navigation/package.json
index e9754a49e..a433feba2 100644
--- a/e2e/nested-frame-navigation/package.json
+++ b/e2e/nested-frame-navigation/package.json
@@ -19,7 +19,6 @@
"devDependencies": {
"@types/chai": "~4.1.7",
"@types/mocha": "~5.2.5",
- "@types/node": "^7.0.5",
"mocha": "~5.2.0",
"mochawesome": "~3.1.2",
"nativescript-dev-appium": "next",
diff --git a/package.json b/package.json
index f0f559373..bc064268a 100644
--- a/package.json
+++ b/package.json
@@ -80,7 +80,7 @@
"test-watch-ios": "npm run pretest && concurrently --kill-others \"npm run tsc-tiw\" \"tns livesync ios --path tests --watch\"",
"prepublish": "echo \"Development reminder for setup\n - tns-core-modules: npm run setup\n - tns-core-modules-widgets: npm run setup-widgets\n\"",
"typedoc": "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\"",
- "dev-typedoc": "npm run typedoc && cd bin/dist/apiref && http-server",
+ "dev-typedoc": "npm run typedoc && cd bin/dist/apiref && npx http-server",
"test-tsc-es2016": "npm run tsc -- -p tsconfig.public.es2016.json",
"tslint": "tslint --config build/tslint.json 'tns-core-modules/**/*.ts' 'tests/**/*.ts' 'apps/**/*.ts' 'e2e/**/*.ts' -e '**/node_modules/**' -e '**/platforms/**'",
"madge-ios": "tsc --skipLibCheck && tns prepare ios --path tests && madge --circular tests/platforms/ios/tests/app/tns_modules/tns-core-modules",
diff --git a/tests/app/ui/image-cache/image-cache-tests.ts b/tests/app/ui/image-cache/image-cache-tests.ts
index c6237b8ac..946cf426b 100644
--- a/tests/app/ui/image-cache/image-cache-tests.ts
+++ b/tests/app/ui/image-cache/image-cache-tests.ts
@@ -1,9 +1,19 @@
import * as imageCacheModule from "tns-core-modules/ui/image-cache";
import * as imageSource from "tns-core-modules/image-source";
import * as types from "tns-core-modules/utils/types";
+import { device } from "tns-core-modules/platform";
+import lazy from "tns-core-modules/utils/lazy";
+
import * as TKUnit from "../../TKUnit";
+const sdkVersion = lazy(() => parseInt(device.sdkVersion));
+
export const test_ImageCache_ValidUrl = function() {
+ // see https://github.com/NativeScript/NativeScript/issues/6643
+ if (sdkVersion() < 20) {
+ return;
+ }
+
const cache = new imageCacheModule.Cache();
cache.maxRequests = 5;
diff --git a/tests/app/ui/label/label-tests.ts b/tests/app/ui/label/label-tests.ts
index 5063e903f..6e4f416af 100644
--- a/tests/app/ui/label/label-tests.ts
+++ b/tests/app/ui/label/label-tests.ts
@@ -162,10 +162,10 @@ export class LabelTest extends testModule.UITest {
const span = new Span();
span.text = "long label";
span.fontWeight = "bold";
-
+
const span2 = new Span();
span2.text = "long label";
-
+
const formattedString = new FormattedString();
formattedString.spans.push(span);
formattedString.spans.push(span2);
@@ -176,7 +176,7 @@ export class LabelTest extends testModule.UITest {
const span3 = new Span();
span3.text = "short label";
span3.fontWeight = "bold";
-
+
const formattedString2 = new FormattedString();
formattedString2.spans.push(span3);
label.formattedText = formattedString2;
@@ -210,7 +210,7 @@ export class LabelTest extends testModule.UITest {
const span = new Span();
span.text = "short label";
span.fontWeight = "bold";
-
+
const formattedString = new FormattedString();
formattedString.spans.push(span);
label.formattedText = formattedString;
@@ -220,10 +220,10 @@ export class LabelTest extends testModule.UITest {
const span2 = new Span();
span2.text = "long label";
span2.fontWeight = "bold";
-
+
const span3 = new Span();
span3.text = "long label";
-
+
const formattedString2 = new FormattedString();
formattedString2.spans.push(span2);
formattedString2.spans.push(span3);
@@ -733,6 +733,21 @@ export class LabelTest extends testModule.UITest {
return host;
});
}
+
+ public test_FormattedText_ShouldNotCrash_WheRemovedFromSpan() {
+ const label = this.testView;
+ label.color = new colorModule.Color("red");
+ this.waitUntilTestElementIsLoaded();
+
+ const span = new Span();
+ span.text = "test";
+
+ const formattedString = new FormattedString();
+ formattedString.spans.push(span);
+
+ label._addChildFromBuilder("FormattedString", formattedString);
+ label._removeView(formattedString);
+ };
}
export function createTestCase(): LabelTest {
diff --git a/tests/app/utils/utils-tests.ts b/tests/app/utils/utils-tests.ts
index 10e07d498..ac9dd2ab0 100644
--- a/tests/app/utils/utils-tests.ts
+++ b/tests/app/utils/utils-tests.ts
@@ -18,6 +18,47 @@ export function test_releaseNativeObject_canBeCalledWithNativeObject() {
}
};
+export function test_executeOnMainThread_Works(done: Function) {
+ utils.executeOnMainThread(() => {
+ try {
+ TKUnit.assertTrue(utils.isMainThread());
+ done();
+ } catch (e) {
+ done(e);
+ }
+ });
+}
+
+export function test_dispatchToMainThread_Works(done: Function) {
+ utils.dispatchToMainThread(() => {
+ try {
+ TKUnit.assertTrue(utils.isMainThread());
+ done();
+ } catch (e) {
+ done(e);
+ }
+ });
+}
+
+export function test_mainThreadify_PassesArgs(done: Function) {
+ const expectedN = 434;
+ const expectedB = true;
+ const expectedS = "string";
+ const f = utils.mainThreadify(function (n: number, b: boolean, s: string) {
+ try {
+ TKUnit.assertTrue(utils.isMainThread());
+ TKUnit.assertEqual(n, expectedN);
+ TKUnit.assertEqual(b, expectedB);
+ TKUnit.assertEqual(s, expectedS);
+ done();
+ } catch (e) {
+ done(e);
+ }
+ });
+
+ f(expectedN, expectedB, expectedS);
+}
+
function test_releaseNativeObject_canBeCalledWithNativeObject_iOS() {
let deallocated = false;
const obj = new ((NSObject).extend({
diff --git a/tns-core-modules-widgets/package.json b/tns-core-modules-widgets/package.json
index 50ed097f7..46bab1160 100644
--- a/tns-core-modules-widgets/package.json
+++ b/tns-core-modules-widgets/package.json
@@ -1,6 +1,6 @@
{
"name": "tns-core-modules-widgets",
- "version": "5.4.0",
+ "version": "6.0.0",
"description": "Native widgets used in the NativeScript framework.",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
diff --git a/tns-core-modules/application/application.ios.ts b/tns-core-modules/application/application.ios.ts
index 3d38f5889..e1d0be781 100644
--- a/tns-core-modules/application/application.ios.ts
+++ b/tns-core-modules/application/application.ios.ts
@@ -10,7 +10,6 @@ import {
notify, launchEvent, resumeEvent, suspendEvent, exitEvent, lowMemoryEvent,
orientationChangedEvent, setApplication, livesync, displayedEvent, getCssFileName
} from "./application-common";
-import { ModuleType } from "../ui/core/view/view-common";
// First reexport so that app module is initialized.
export * from "./application-common";
@@ -231,7 +230,7 @@ class IOSApplication implements IOSApplicationDefinition {
public _onLivesync(context?: ModuleContext): void {
// Handle application root module
- const isAppRootModuleChanged = context && context.path && context.path.includes(getMainEntry().moduleName) && context.type !== ModuleType.style;
+ const isAppRootModuleChanged = context && context.path && context.path.includes(getMainEntry().moduleName) && context.type !== "style";
// Set window content when:
// + Application root module is changed
diff --git a/tns-core-modules/debugger/devtools-elements.common.ts b/tns-core-modules/debugger/devtools-elements.common.ts
index 186cfe320..c0b7ac43f 100644
--- a/tns-core-modules/debugger/devtools-elements.common.ts
+++ b/tns-core-modules/debugger/devtools-elements.common.ts
@@ -2,6 +2,7 @@ import { getNodeById } from "./dom-node";
// Needed for typings only
import { ViewBase } from "../ui/core/view-base";
+import { mainThreadify } from "../utils/utils";
// Use lazy requires for core modules
const frameTopmost = () => require("../ui/frame").topmost();
@@ -11,7 +12,7 @@ function unsetViewValue(view, name) {
if (!unsetValue) {
unsetValue = require("../ui/core/properties").unsetValue;
}
-
+
view[name] = unsetValue;
}
@@ -30,10 +31,10 @@ export function getDocument() {
if (!topMostFrame) {
return undefined;
}
-
+
try {
topMostFrame.ensureDomNode();
-
+
} catch (e) {
console.log("ERROR in getDocument(): " + e);
}
@@ -49,7 +50,7 @@ export function getComputedStylesForNode(nodeId): Array<{ name: string, value: s
return [];
}
-export function removeNode(nodeId) {
+export const removeNode = mainThreadify(function removeNode(nodeId) {
const view = getViewById(nodeId);
if (view) {
// Avoid importing layout and content view
@@ -63,9 +64,9 @@ export function removeNode(nodeId) {
console.log("Can't remove child from " + parent);
}
}
-}
+});
-export function setAttributeAsText(nodeId, text, name) {
+export const setAttributeAsText = mainThreadify(function setAttributeAsText(nodeId, text, name) {
const view = getViewById(nodeId);
if (view) {
// attribute is registered for the view instance
@@ -93,4 +94,4 @@ export function setAttributeAsText(nodeId, text, name) {
view.domNode.loadAttributes();
}
-}
+});
diff --git a/tns-core-modules/module.d.ts b/tns-core-modules/module.d.ts
index 573831c1b..f65cd0310 100644
--- a/tns-core-modules/module.d.ts
+++ b/tns-core-modules/module.d.ts
@@ -66,11 +66,7 @@ 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 ModuleType {
- markup = "markup",
- script = "script",
- style = "style"
-}
+declare type ModuleType = "markup" | "script" | "style";
/**
* Define a module context for Hot Module Replacement.
diff --git a/tns-core-modules/package.json b/tns-core-modules/package.json
index 91a26be78..2be229ac8 100644
--- a/tns-core-modules/package.json
+++ b/tns-core-modules/package.json
@@ -1,7 +1,7 @@
{
"name": "tns-core-modules",
"description": "Telerik NativeScript Core Modules",
- "version": "5.4.0",
+ "version": "6.0.0",
"homepage": "https://www.nativescript.org",
"repository": {
"type": "git",
diff --git a/tns-core-modules/ui/button/button.android.ts b/tns-core-modules/ui/button/button.android.ts
index 66db08e2d..2acbf475d 100644
--- a/tns-core-modules/ui/button/button.android.ts
+++ b/tns-core-modules/ui/button/button.android.ts
@@ -5,9 +5,13 @@
} from "./button-common";
import { profile } from "../../profiling";
import { TouchGestureEventData, GestureTypes, TouchAction } from "../gestures";
+import { device } from "../../platform";
+import lazy from "../../utils/lazy";
export * from "./button-common";
+const sdkVersion = lazy(() => parseInt(device.sdkVersion));
+
interface ClickListener {
new(owner: Button): android.view.View.OnClickListener;
}
@@ -151,4 +155,23 @@ export class Button extends ButtonBase {
const newValue = value === "initial" ? "center" : value;
super[textAlignmentProperty.setNative](newValue);
}
-}
\ No newline at end of file
+
+ protected getDefaultElevation(): number {
+ if (sdkVersion() < 21) {
+ return 0;
+ }
+
+ // NOTE: Button widget has StateListAnimator that defines the elevation value and
+ // at the time of the getDefault() query the animator is not applied yet so we
+ // return the hardcoded @dimen/button_elevation_material value 2dp here instead
+ return 2;
+ }
+
+ protected getDefaultDynamicElevationOffset(): number {
+ if (sdkVersion() < 21) {
+ return 0;
+ }
+
+ return 4; // 4dp @dimen/button_pressed_z_material
+ }
+}
diff --git a/tns-core-modules/ui/core/view-base/view-base.ts b/tns-core-modules/ui/core/view-base/view-base.ts
index 1863ce05d..caf868b0c 100644
--- a/tns-core-modules/ui/core/view-base/view-base.ts
+++ b/tns-core-modules/ui/core/view-base/view-base.ts
@@ -1018,7 +1018,7 @@ export const classNameProperty = new Property({
valueChanged(view: ViewBase, oldValue: string, newValue: string) {
let classes = view.cssClasses;
classes.clear();
- if (typeof newValue === "string") {
+ if (typeof newValue === "string" && newValue !== "") {
newValue.split(" ").forEach(c => classes.add(c));
}
view._onCssStateChange();
diff --git a/tns-core-modules/ui/core/view/view-common.ts b/tns-core-modules/ui/core/view/view-common.ts
index a9c627a84..166f2205e 100644
--- a/tns-core-modules/ui/core/view/view-common.ts
+++ b/tns-core-modules/ui/core/view/view-common.ts
@@ -21,6 +21,7 @@ import {
} from "../../gestures";
import { createViewFromEntry } from "../../builder";
+import { isAndroid } from "../../../platform";
import { StyleScope } from "../../styling/style-scope";
import { LinearGradient } from "../../styling/linear-gradient";
import { BackgroundRepeat } from "../../styling/style-properties";
@@ -37,18 +38,25 @@ function ensureAnimationModule() {
}
}
-export enum ModuleType {
- markup = "markup",
- script = "script",
- style = "style"
-}
-
export function CSSType(type: string): ClassDecorator {
return (cls) => {
cls.prototype.cssType = type;
};
}
+export function viewMatchesModuleContext(
+ view: ViewDefinition,
+ context: ModuleContext,
+ types: ModuleType[]): boolean {
+
+ return context &&
+ view._moduleName &&
+ context.type &&
+ types.some(type => type === context.type) &&
+ context.path &&
+ context.path.includes(view._moduleName);
+}
+
export function PseudoClassHandler(...pseudoClasses: string[]): MethodDecorator {
const stateEventNames = pseudoClasses.map(s => ":" + s);
const listeners = Symbol("listeners");
@@ -147,62 +155,36 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition {
traceWrite(`${this}._onLivesync(${JSON.stringify(context)})`, traceCategories.Livesync);
}
- _rootModalViews.forEach(v => v.closeModal());
- _rootModalViews.length = 0;
-
- if (context && context.type && context.path) {
- // Handle local styles
- if (context.type === ModuleType.style) {
- return this.changeLocalStyles(context.path);
- }
- // Handle module markup and script changes
- else {
- return this.changeModule(context);
- }
- }
-
- return false;
- }
-
- private changeLocalStyles(contextPath: string): boolean {
- if (!this.changeStyles(this, contextPath)) {
- eachDescendant(this, (child: ViewBase) => {
- this.changeStyles(child, contextPath);
- return true;
- });
- }
-
- // Do not reset activity/window content for local styles changes
- return true;
- }
-
- private changeStyles(view: ViewBase, contextPath: string): boolean {
- if (traceEnabled()) {
- traceWrite(`${view}.${view._moduleName}`, traceCategories.Livesync);
- }
-
- if (view._moduleName && contextPath.includes(view._moduleName)) {
- (view).changeCssFile(contextPath);
+ if (this._handleLivesync(context)) {
return true;
}
- return false;
- }
- private changeModule(context: ModuleContext): boolean {
- eachDescendant(this, (child: ViewBase) => {
- if (traceEnabled()) {
- traceWrite(`${child}.${child._moduleName}`, traceCategories.Livesync);
+ let handled = false;
+ this.eachChildView((child) => {
+ if (child._onLivesync(context)) {
+ handled = true;
+ return false;
}
-
- // Handle changes in module's Page
- if (child._moduleName && context.path.includes(child._moduleName) && child.page) {
- child.page._onLivesync(context);
- }
- return true;
});
+ return handled;
+ }
- // Do not reset activity/window content for module changes
- return true;
+ public _handleLivesync(context?: ModuleContext): boolean {
+ if (traceEnabled()) {
+ traceWrite(`${this}._handleLivesync(${JSON.stringify(context)})`, traceCategories.Livesync);
+ }
+
+ // Handle local CSS
+ if (viewMatchesModuleContext(this, context, ["style"])) {
+ if (traceEnabled()) {
+ traceWrite(`Change Handled: Changing CSS for ${this}`, traceCategories.Livesync);
+ }
+
+ this.changeCssFile(context.path);
+ return true;
+ }
+
+ return false;
}
_setupAsRootView(context: any): void {
@@ -368,7 +350,11 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition {
}
}
- that._hideNativeModalView(parent, whenClosedCallback);
+ if (isAndroid || (parent.viewController && parent.viewController.presentedViewController)) {
+ that._hideNativeModalView(parent, whenClosedCallback);
+ } else {
+ whenClosedCallback();
+ }
}
};
}
@@ -697,6 +683,20 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition {
this.style.scaleY = value;
}
+ get androidElevation(): number {
+ return this.style.androidElevation;
+ }
+ set androidElevation(value: number) {
+ this.style.androidElevation = value;
+ }
+
+ get androidDynamicElevationOffset(): number {
+ return this.style.androidDynamicElevationOffset;
+ }
+ set androidDynamicElevationOffset(value: number) {
+ this.style.androidDynamicElevationOffset = value;
+ }
+
//END Style property shortcuts
public automationText: string;
diff --git a/tns-core-modules/ui/core/view/view.android.ts b/tns-core-modules/ui/core/view/view.android.ts
index 7e27b8e5a..0f6e936e4 100644
--- a/tns-core-modules/ui/core/view/view.android.ts
+++ b/tns-core-modules/ui/core/view/view.android.ts
@@ -15,19 +15,27 @@ import {
minWidthProperty, minHeightProperty, widthProperty, heightProperty,
marginLeftProperty, marginTopProperty, marginRightProperty, marginBottomProperty,
rotateProperty, scaleXProperty, scaleYProperty, translateXProperty, translateYProperty,
- zIndexProperty, backgroundInternalProperty
+ zIndexProperty, backgroundInternalProperty, androidElevationProperty, androidDynamicElevationOffsetProperty
} from "../../styling/style-properties";
import { Background, ad as androidBackground } from "../../styling/background";
import { profile } from "../../../profiling";
import { topmost } from "../../frame/frame-stack";
import { AndroidActivityBackPressedEventData, android as androidApp } from "../../../application";
+import { device } from "../../../platform";
+import lazy from "../../../utils/lazy";
export * from "./view-common";
const DOMID = "_domId";
const androidBackPressedEvent = "androidBackPressed";
+const shortAnimTime = 17694720; // android.R.integer.config_shortAnimTime
+const statePressed = 16842919; // android.R.attr.state_pressed
+const stateEnabled = 16842910; // android.R.attr.state_enabled
+
+const sdkVersion = lazy(() => parseInt(device.sdkVersion));
+
const modalMap = new Map();
let TouchListener: TouchListener;
@@ -255,6 +263,8 @@ export class View extends ViewCommon {
private layoutChangeListener: android.view.View.OnLayoutChangeListener;
private _manager: android.support.v4.app.FragmentManager;
private _rootManager: android.support.v4.app.FragmentManager;
+ private _originalElevation: number;
+ private _originalStateListAnimator: any; /* android.animation.StateListAnimator; */
nativeViewProtected: android.view.View;
@@ -709,6 +719,94 @@ export class View extends ViewCommon {
this.nativeViewProtected.setAlpha(float(value));
}
+ [androidElevationProperty.getDefault](): number {
+ return this.getDefaultElevation();
+ }
+ [androidElevationProperty.setNative](value: number) {
+ if (sdkVersion() < 21) {
+ return;
+ }
+
+ this.refreshStateListAnimator();
+ }
+
+ [androidDynamicElevationOffsetProperty.getDefault](): number {
+ return this.getDefaultDynamicElevationOffset();
+ }
+ [androidDynamicElevationOffsetProperty.setNative](value: number) {
+ if (sdkVersion() < 21) {
+ return;
+ }
+
+ this.refreshStateListAnimator();
+ }
+
+ protected getDefaultElevation(): number {
+ if (sdkVersion() < 21) {
+ return 0;
+ }
+
+ // NOTE: overriden in Button implementation as for widgets with StateListAnimator (Button)
+ // nativeView.getElevation() returns 0 at the time of the getDefault() query
+ return layout.toDeviceIndependentPixels((this.nativeViewProtected).getElevation());
+ }
+
+ protected getDefaultDynamicElevationOffset() {
+ // NOTE: overriden in Button implementation
+ return 0;
+ }
+
+ private refreshStateListAnimator() {
+ const nativeView: any = this.nativeViewProtected;
+
+ const ObjectAnimator = android.animation.ObjectAnimator;
+ const AnimatorSet = android.animation.AnimatorSet;
+
+ const duration = nativeView.getContext().getResources().getInteger(shortAnimTime) / 2;
+
+ let elevation = this.androidElevation;
+ if (typeof elevation === "undefined" || elevation === null) {
+ elevation = this.getDefaultElevation();
+ }
+ elevation = layout.toDevicePixels(elevation);
+
+ const z = layout.toDevicePixels(0);
+
+ let pressedZ = this.androidDynamicElevationOffset;
+ if (typeof pressedZ === "undefined" || pressedZ === null) {
+ pressedZ = this.getDefaultDynamicElevationOffset();
+ }
+ pressedZ = layout.toDevicePixels(pressedZ);
+
+ const pressedSet = new AnimatorSet();
+ pressedSet.playTogether(java.util.Arrays.asList([
+ ObjectAnimator.ofFloat(nativeView, "translationZ", [pressedZ])
+ .setDuration(duration),
+ ObjectAnimator.ofFloat(nativeView, "elevation", [elevation])
+ .setDuration(0),
+ ]));
+
+ const notPressedSet = new AnimatorSet();
+ notPressedSet.playTogether(java.util.Arrays.asList([
+ ObjectAnimator.ofFloat(nativeView, "translationZ", [z])
+ .setDuration(duration),
+ ObjectAnimator.ofFloat(nativeView, "elevation", [elevation])
+ .setDuration(0),
+ ]));
+
+ const defaultSet = new AnimatorSet();
+ defaultSet.playTogether(java.util.Arrays.asList([
+ ObjectAnimator.ofFloat(nativeView, "translationZ", [0]).setDuration(0),
+ ObjectAnimator.ofFloat(nativeView, "elevation", [0]).setDuration(0),
+ ]));
+
+ const stateListAnimator = new (android.animation).StateListAnimator();
+ stateListAnimator.addState([statePressed, stateEnabled], pressedSet);
+ stateListAnimator.addState([stateEnabled], notPressedSet);
+ stateListAnimator.addState([], defaultSet);
+ nativeView.setStateListAnimator(stateListAnimator);
+ }
+
[horizontalAlignmentProperty.getDefault](): HorizontalAlignment {
return org.nativescript.widgets.ViewHelper.getHorizontalAlignment(this.nativeViewProtected);
}
@@ -946,7 +1044,7 @@ function createNativePercentLengthProperty(options: NativePercentLengthPropertyO
const { getter, setter, auto = 0 } = options;
let setPixels, getPixels, setPercent;
if (getter) {
- View.prototype[getter] = function (this: View): PercentLength {
+ View.prototype[getter] = function(this: View): PercentLength {
if (options) {
setPixels = options.setPixels;
getPixels = options.getPixels;
@@ -962,7 +1060,7 @@ function createNativePercentLengthProperty(options: NativePercentLengthPropertyO
}
}
if (setter) {
- View.prototype[setter] = function (this: View, length: PercentLength) {
+ View.prototype[setter] = function(this: View, length: PercentLength) {
if (options) {
setPixels = options.setPixels;
getPixels = options.getPixels;
diff --git a/tns-core-modules/ui/core/view/view.d.ts b/tns-core-modules/ui/core/view/view.d.ts
index 1e4d7dcc2..5325ab9ed 100644
--- a/tns-core-modules/ui/core/view/view.d.ts
+++ b/tns-core-modules/ui/core/view/view.d.ts
@@ -32,6 +32,17 @@ export function PseudoClassHandler(...pseudoClasses: string[]): MethodDecorator;
*/
export function CSSType(type: string): ClassDecorator;
+/**
+ *
+ * @param view The view
+ * @param context The ModuleType
+ * @param type Type of the ModuleType to be matched
+ */
+export function viewMatchesModuleContext(
+ view: View,
+ context: ModuleContext,
+ type: ModuleType[]): boolean;
+
/**
* Denotes a length number that is in device independent pixel units.
*/
@@ -213,6 +224,16 @@ export abstract class View extends ViewBase {
*/
color: Color;
+ /**
+ * Gets or sets the elevation of the android view.
+ */
+ androidElevation: number;
+
+ /**
+ * Gets or sets the dynamic elevation offset of the android view.
+ */
+ androidDynamicElevationOffset: number;
+
/**
* Gets or sets the background style property.
*/
@@ -474,7 +495,7 @@ export abstract class View extends ViewBase {
/**
* @deprecated use on() instead
- *
+ *
* @param type - Type of the gesture.
* @param callback - A function that will be executed when gesture is received.
* @param thisArg - An optional parameter which will be used as `this` context for callback execution.
@@ -683,6 +704,10 @@ export abstract class View extends ViewBase {
* @private
*/
_onLivesync(context?: { type: string, path: string }): boolean;
+ /**
+ * @private
+ */
+ _handleLivesync(context?: { type: string, path: string }): boolean;
/**
* @private
*/
diff --git a/tns-core-modules/ui/core/view/view.ios.ts b/tns-core-modules/ui/core/view/view.ios.ts
index c733f9066..99cd1ad43 100644
--- a/tns-core-modules/ui/core/view/view.ios.ts
+++ b/tns-core-modules/ui/core/view/view.ios.ts
@@ -29,6 +29,7 @@ const majorVersion = iosUtils.MajorVersion;
export class View extends ViewCommon {
nativeViewProtected: UIView;
viewController: UIViewController;
+ private _popoverPresentationDelegate: ios.UIPopoverPresentationControllerDelegateImp;
private _isLaidOut = false;
private _hasTransfrom = false;
@@ -416,6 +417,8 @@ export class View extends ViewCommon {
if (presentationStyle === UIModalPresentationStyle.Popover) {
const popoverPresentationController = controller.popoverPresentationController;
+ this._popoverPresentationDelegate = ios.UIPopoverPresentationControllerDelegateImp.initWithOwnerAndCallback(new WeakRef(this), this._closeModalCallback);
+ popoverPresentationController.delegate = this._popoverPresentationDelegate;
const view = parent.nativeViewProtected;
// Note: sourceView and sourceRect are needed to specify the anchor location for the popover.
// Note: sourceView should be the button triggering the modal. If it the Page the popover might appear "behind" the page content
@@ -906,7 +909,7 @@ export namespace ios {
public viewDidLoad(): void {
super.viewDidLoad();
-
+
// Unify translucent and opaque bars layout
// this.edgesForExtendedLayout = UIRectEdgeBottom;
this.extendedLayoutIncludesOpaqueBars = true;
@@ -982,4 +985,26 @@ export namespace ios {
}
}
}
+
+ export class UIPopoverPresentationControllerDelegateImp extends NSObject implements UIPopoverPresentationControllerDelegate {
+ public static ObjCProtocols = [UIPopoverPresentationControllerDelegate];
+
+ private owner: WeakRef;
+ private closedCallback: Function;
+
+ public static initWithOwnerAndCallback(owner: WeakRef, whenClosedCallback: Function): UIPopoverPresentationControllerDelegateImp {
+ const instance = super.new();
+ instance.owner = owner;
+ instance.closedCallback = whenClosedCallback;
+
+ return instance;
+ }
+
+ public popoverPresentationControllerDidDismissPopover(popoverPresentationController: UIPopoverPresentationController) {
+ const owner = this.owner.get();
+ if (owner && typeof this.closedCallback === "function") {
+ this.closedCallback();
+ }
+ }
+ }
}
diff --git a/tns-core-modules/ui/frame/frame-common.ts b/tns-core-modules/ui/frame/frame-common.ts
index 1346385e0..ef7fbd470 100644
--- a/tns-core-modules/ui/frame/frame-common.ts
+++ b/tns-core-modules/ui/frame/frame-common.ts
@@ -3,12 +3,13 @@ import { Frame as FrameDefinition, NavigationEntry, BackstackEntry, NavigationTr
import { Page } from "../page";
// Types.
-import { getAncestor } from "../core/view/view-common";
+import { getAncestor, viewMatchesModuleContext } from "../core/view/view-common";
import { View, CustomLayoutView, isIOS, isAndroid, traceEnabled, traceWrite, traceCategories, Property, CSSType } from "../core/view";
import { createViewFromEntry } from "../builder";
import { profile } from "../../profiling";
import { frameStack, topmost as frameStackTopmost, _pushInFrameStack, _popFromFrameStack, _removeFromFrameStack } from "./frame-stack";
+import { getModuleName } from "../../utils/utils";
export * from "../core/view";
export enum NavigationType {
@@ -574,7 +575,38 @@ export class FrameBase extends CustomLayoutView implements FrameDefinition {
return result;
}
- public _onLivesync(): boolean {
+ public _onLivesync(context?: ModuleContext): boolean {
+ if (super._onLivesync(context)) {
+ return true;
+ }
+
+ // Fallback
+ if (!context) {
+ return this.legacyLivesync();
+ }
+
+ return false;
+ }
+
+ public _handleLivesync(context?: ModuleContext): boolean {
+ if (super._handleLivesync(context)) {
+ return true;
+ }
+
+ // Handle markup/script changes in currentPage
+ if (this.currentPage &&
+ viewMatchesModuleContext(this.currentPage, context, ["markup", "script"])) {
+
+ traceWrite(`Change Handled: Replacing page ${context.path}`, traceCategories.Livesync);
+
+ this.replacePage(context);
+ return true;
+ }
+
+ return false;
+ }
+
+ private legacyLivesync(): boolean {
// Reset activity/window content when:
// + Changes are not handled on View
// + There is no ModuleContext
@@ -609,6 +641,27 @@ export class FrameBase extends CustomLayoutView implements FrameDefinition {
this.navigate(newEntry);
return true;
}
+
+ protected replacePage(context: ModuleContext): void {
+ // Set NavigationType.replace for HMR.
+ // In IOS on `viewDidAppear()` this will be set to NavigationType.forward.
+ this.navigationType = NavigationType.replace;
+ const currentBackstackEntry = this._currentEntry;
+ const contextModuleName = getModuleName(context.path);
+
+ const newPage = createViewFromEntry({ moduleName: contextModuleName });
+ const newBackstackEntry: BackstackEntry = {
+ entry: currentBackstackEntry.entry,
+ resolvedPage: newPage,
+ navDepth: currentBackstackEntry.navDepth,
+ fragmentTag: currentBackstackEntry.fragmentTag,
+ frameId: currentBackstackEntry.frameId
+ };
+
+ const navContext: NavigationContext = { entry: newBackstackEntry, isBackNavigation: false };
+ this.performNavigation(navContext);
+ }
+
}
export function getFrameById(id: string): FrameBase {
diff --git a/tns-core-modules/ui/frame/frame.android.ts b/tns-core-modules/ui/frame/frame.android.ts
index 0192ec102..7151448e3 100644
--- a/tns-core-modules/ui/frame/frame.android.ts
+++ b/tns-core-modules/ui/frame/frame.android.ts
@@ -3,7 +3,6 @@ import {
AndroidFrame as AndroidFrameDefinition, AndroidActivityCallbacks,
AndroidFragmentCallbacks, BackstackEntry, NavigationTransition
} from ".";
-import { ModuleType } from "../../ui/core/view/view-common";
import { Page } from "../page";
// Types.
@@ -90,7 +89,7 @@ export function reloadPage(context?: ModuleContext): void {
if (callbacks) {
const rootView: View = callbacks.getRootView();
// Handle application root module
- const isAppRootModuleChanged = context && context.path && context.path.includes(application.getMainEntry().moduleName) && context.type !== ModuleType.style;
+ const isAppRootModuleChanged = context && context.path && context.path.includes(application.getMainEntry().moduleName) && context.type !== "style";
// Reset activity content when:
// + Application root module is changed
@@ -339,39 +338,6 @@ export class Frame extends FrameBase {
return false;
}
- public _onLivesync(context?: ModuleContext): boolean {
- if (traceEnabled()) {
- traceWrite(`${this}._onLivesync(${JSON.stringify(context)})`, traceCategories.Livesync);
- }
-
- if (!this._currentEntry || !this._currentEntry.entry) {
- return false;
- }
-
- if (context && context.type && context.path) {
- // Set NavigationType.replace for HMR.
- this.navigationType = NavigationType.replace;
- const currentBackstackEntry = this._currentEntry;
- const contextModuleName = getModuleName(context.path);
-
- const newPage = createViewFromEntry({ moduleName: contextModuleName });
- const newBackstackEntry: BackstackEntry = {
- entry: currentBackstackEntry.entry,
- resolvedPage: newPage,
- navDepth: currentBackstackEntry.navDepth,
- fragmentTag: currentBackstackEntry.fragmentTag,
- frameId: currentBackstackEntry.frameId
- };
-
- const navContext: NavigationContext = { entry: newBackstackEntry, isBackNavigation: false };
- this.performNavigation(navContext);
- return true;
- } else {
- // Fallback
- return super._onLivesync();
- }
- }
-
@profile
public _navigateCore(newEntry: BackstackEntry) {
super._navigateCore(newEntry);
diff --git a/tns-core-modules/ui/frame/frame.ios.ts b/tns-core-modules/ui/frame/frame.ios.ts
index d85cc5189..a9a985b0c 100644
--- a/tns-core-modules/ui/frame/frame.ios.ts
+++ b/tns-core-modules/ui/frame/frame.ios.ts
@@ -63,39 +63,6 @@ export class Frame extends FrameBase {
}
}
- public _onLivesync(context?: ModuleContext): boolean {
- if (traceEnabled()) {
- traceWrite(`${this}._onLivesync(${JSON.stringify(context)})`, traceCategories.Livesync);
- }
-
- if (!this._currentEntry || !this._currentEntry.entry) {
- return false;
- }
-
- if (context && context.type && context.path) {
- // Set NavigationType.replace for HMR.
- // When `viewDidAppear()` set to NavigationType.forward.
- this.navigationType = NavigationType.replace;
- const currentBackstackEntry = this._currentEntry;
-
- const contextModuleName = utils.getModuleName(context.path);
- const newPage = createViewFromEntry({ moduleName: contextModuleName });
- const newBackstackEntry: BackstackEntry = {
- entry: currentBackstackEntry.entry,
- resolvedPage: newPage,
- navDepth: currentBackstackEntry.navDepth,
- fragmentTag: undefined
- }
-
- const navContext: NavigationContext = { entry: newBackstackEntry, isBackNavigation: false };
- this.performNavigation(navContext);
- return true;
- } else {
- // Fallback
- return super._onLivesync();
- }
- }
-
@profile
public _navigateCore(backstackEntry: BackstackEntry) {
// NavigationType.replace for HMR.
diff --git a/tns-core-modules/ui/page/page-common.ts b/tns-core-modules/ui/page/page-common.ts
index f8c152c71..689781083 100644
--- a/tns-core-modules/ui/page/page-common.ts
+++ b/tns-core-modules/ui/page/page-common.ts
@@ -99,10 +99,6 @@ export class PageBase extends ContentView implements PageDefinition {
};
}
- public _onLivesync(context?: ModuleContext): boolean {
- return this.frame ? this.frame._onLivesync(context) : false;
- }
-
@profile
public onNavigatingTo(context: any, isBackNavigation: boolean, bindingContext?: any) {
this._navigationContext = context;
diff --git a/tns-core-modules/ui/styling/style-properties.ts b/tns-core-modules/ui/styling/style-properties.ts
index 47489ece1..430114895 100644
--- a/tns-core-modules/ui/styling/style-properties.ts
+++ b/tns-core-modules/ui/styling/style-properties.ts
@@ -1127,3 +1127,9 @@ export const visibilityProperty = new CssProperty