diff --git a/tests/app/livesync/livesync-modal-view-page.css b/tests/app/livesync/livesync-modal-view-page.css
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/tests/app/livesync/livesync-modal-view-page.scss b/tests/app/livesync/livesync-modal-view-page.scss
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/tests/app/livesync/livesync-modal-view-page.ts b/tests/app/livesync/livesync-modal-view-page.ts
new file mode 100644
index 0000000000..6160a186b2
--- /dev/null
+++ b/tests/app/livesync/livesync-modal-view-page.ts
@@ -0,0 +1,15 @@
+import { View, ShowModalOptions } from "tns-core-modules/ui/core/view";
+const LIVESYNC_FOLDER = "livesync/";
+const buttonPageModuleName = `${LIVESYNC_FOLDER}livesync-button-page`;
+
+export function onLoaded(args) {
+ const view = args.object as View;
+
+ let options: ShowModalOptions = {
+ context: "context",
+ closeCallback: () => console.log("modal view closeCallback raised."),
+ animated: false
+ };
+
+ view.showModal(buttonPageModuleName, options);
+}
diff --git a/tests/app/livesync/livesync-modal-view-page.xml b/tests/app/livesync/livesync-modal-view-page.xml
new file mode 100644
index 0000000000..8b5ae3cd1d
--- /dev/null
+++ b/tests/app/livesync/livesync-modal-view-page.xml
@@ -0,0 +1,3 @@
+
+
+
diff --git a/tests/app/livesync/livesync-tests.ts b/tests/app/livesync/livesync-tests.ts
index 7bf950f906..2ede70f509 100644
--- a/tests/app/livesync/livesync-tests.ts
+++ b/tests/app/livesync/livesync-tests.ts
@@ -30,6 +30,13 @@ const buttonTsPageFileName = `${LIVESYNC_FOLDER}livesync-button-page.ts`;
const buttonScssPageFileName = `${LIVESYNC_FOLDER}livesync-button-page.scss`;
const labelPageModuleName = `${LIVESYNC_FOLDER}livesync-label-page`;
+const modalViewPageModuleName = `${LIVESYNC_FOLDER}livesync-modal-view-page`;
+const modalViewXmlPageFileName = `${LIVESYNC_FOLDER}livesync-modal-view-page.xml`;
+const modalViewJsPageFileName = `${LIVESYNC_FOLDER}livesync-modal-view-page.js`;
+const modalViewTsPageFileName = `${LIVESYNC_FOLDER}livesync-modal-view-page.ts`;
+const modalViewScssPageFileName = `${LIVESYNC_FOLDER}livesync-modal-view-page.scss`;
+const modalViewCssFileName = `${LIVESYNC_FOLDER}livesync-modal-view-page.css`;
+
const green = new Color("green");
export function setUp() {
@@ -111,6 +118,26 @@ export function test_onLiveSync_ModuleContext_MarkupHtml_ScriptTs_StyleScss_File
]);
}
+export function test_onLiveSync_ModalViewClosed_MarkupXml() {
+ _test_onLiveSync_ModalViewClosed({ type: "markup", path: modalViewXmlPageFileName });
+}
+
+export function test_onLiveSync_ModalViewClosed_ScriptTs() {
+ _test_onLiveSync_ModalViewClosed({ type: "script", path: modalViewTsPageFileName });
+}
+
+export function test_onLiveSync_ModalViewClosed_ScriptJs() {
+ _test_onLiveSync_ModalViewClosed({ type: "script", path: modalViewJsPageFileName });
+}
+
+export function test_onLiveSync_ModalViewClosed_StyleCss() {
+ _test_onLiveSync_ModalViewClosed({ type: "style", path: modalViewCssFileName });
+}
+
+export function test_onLiveSync_ModalViewClosed_StyleScss() {
+ _test_onLiveSync_ModalViewClosed({ type: "style", path: modalViewScssPageFileName });
+}
+
function _test_onLiveSync_ModuleContext_AppStyle(appStyleFileName: string, livesyncStyleFileName: string) {
const pageBeforeNavigation = helper.getCurrentPage();
const buttonPage = createViewFromEntry(({ moduleName: buttonPageModuleName }));
@@ -209,6 +236,18 @@ function _test_onLiveSync_ModuleReplace_Multiple(context: ModuleContext[]) {
TKUnit.assertEqual(pageBeforeNavigation, pageAfterBackNavigation, "Pages are different!");
}
+function _test_onLiveSync_ModalViewClosed(context: ModuleContext) {
+ const modalViewPage = createViewFromEntry(({ moduleName: modalViewPageModuleName }));
+ helper.navigateWithHistory(() => modalViewPage);
+ livesync({ type: context.type, path: context.path });
+
+ TKUnit.waitUntilReady(() => !!frame.topmost());
+ const topmostFrame = frame.topmost();
+ TKUnit.waitUntilReady(() => topmostFrame.currentPage && topmostFrame.currentPage.isLoaded && topmostFrame.canGoBack());
+
+ TKUnit.assertTrue(topmostFrame._getRootModalViews().length === 0);
+}
+
function livesync(context: ModuleContext) {
const ls = (global).__hmrSyncBackup || global.__onLiveSync;
ls(context);
diff --git a/tns-core-modules/ui/core/view/view-common.ts b/tns-core-modules/ui/core/view/view-common.ts
index 255bd35bf8..059e9e23de 100644
--- a/tns-core-modules/ui/core/view/view-common.ts
+++ b/tns-core-modules/ui/core/view/view-common.ts
@@ -152,11 +152,31 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition {
}
}
+ public _closeAllModalViewsInternal(): boolean {
+ if (_rootModalViews && _rootModalViews.length > 0) {
+ _rootModalViews.forEach(v => {
+ v.closeModal();
+ });
+
+ return true;
+ }
+
+ return false;
+ }
+
+ public _getRootModalViews(): Array {
+ return _rootModalViews;
+ }
+
public _onLivesync(context?: ModuleContext): boolean {
if (traceEnabled()) {
traceWrite(`${this}._onLivesync(${JSON.stringify(context)})`, traceCategories.Livesync);
}
+ if (this._closeAllModalViewsInternal()) {
+ return true;
+ }
+
if (this._handleLivesync(context)) {
return true;
}
diff --git a/tns-core-modules/ui/core/view/view.d.ts b/tns-core-modules/ui/core/view/view.d.ts
index 9015fbcf9f..f0ba11898f 100644
--- a/tns-core-modules/ui/core/view/view.d.ts
+++ b/tns-core-modules/ui/core/view/view.d.ts
@@ -610,6 +610,18 @@ export abstract class View extends ViewBase {
// Lifecycle events
_getNativeViewsCount(): number;
+ /**
+ * Internal method:
+ * Closes all modal views. Should be used by plugins like `nativescript-angular` which implement their own `modal views` service.
+ */
+ _closeAllModalViewsInternal(): boolean;
+
+ /**
+ * Internal method:
+ * Gets all modal views of the current view.
+ */
+ _getRootModalViews(): Array
+
_eachLayoutView(callback: (View) => void): void;
/**