Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 17 additions & 20 deletions apps/app/ui-tests-app/modal-view/login-page.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,29 @@
import * as pages from "tns-core-modules/ui/page";
import * as textField from "tns-core-modules/ui/text-field";
import * as observable from "tns-core-modules/data/observable";
import { Page, ShownModallyData } from "tns-core-modules/ui/page";
import { EventData, fromObject } from "tns-core-modules/data/observable";

var context: any;
var closeCallback: Function;
export function onShowingModally(args: ShownModallyData) {
console.log("login-page.onShowingModally, context: " + args.context);
const page = <Page>args.object;

var page: pages.Page;
var usernameTextField: textField.TextField;
var passwordTextField: textField.TextField;
page.bindingContext = fromObject({
username: "username",
password: "password",
context: args.context,
onLoginButtonTap: function() {
console.log("login-page.onLoginButtonTap");
args.closeCallback(this.username, this.password);
}
})
}

export function onShownModally(args: pages.ShownModallyData) {
export function onShownModally(args: ShownModallyData) {
console.log("login-page.onShownModally, context: " + args.context);
context = args.context;
closeCallback = args.closeCallback;
}

export function onLoaded(args: observable.EventData) {
export function onLoaded(args: EventData) {
console.log("login-page.onLoaded");
page = <pages.Page>args.object;
usernameTextField = page.getViewById<textField.TextField>("username");
passwordTextField = page.getViewById<textField.TextField>("password");
}

export function onUnloaded() {
console.log("login-page.onUnloaded");
}

export function onLoginButtonTap() {
console.log("login-page.onLoginButtonTap");
closeCallback(usernameTextField.text, passwordTextField.text);
}
11 changes: 7 additions & 4 deletions apps/app/ui-tests-app/modal-view/login-page.xml
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
<Page xmlns="http://schemas.nativescript.org/tns.xsd" shownModally="onShownModally"
<Page xmlns="http://schemas.nativescript.org/tns.xsd"
showingModally="onShowingModally"
shownModally="onShownModally"
loaded="onLoaded" unloaded="onUnloaded" backgroundColor="Red">
<StackLayout backgroundColor="PaleGreen" margin="10">
<TextField hint="username" id="username" text="username"/>
<TextField hint="password" id="password" text="password" secure="true"/>
<Button text="Login" tap="onLoginButtonTap"/>
<Label text="{{ context }}"/>
<TextField hint="username" text="{{ username }}"/>
<TextField hint="password" text="{{ password }}" secure="true"/>
<Button text="Login" tap="{{ onLoginButtonTap }}"/>
</StackLayout>
</Page>
32 changes: 31 additions & 1 deletion apps/app/ui-tests-app/modal-view/modal-view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,39 @@ export function onTapStretched(args) {
const label = page.getViewById<Label>("label");
var fullscreen = false;
var stretched = true;

page.showModal("ui-tests-app/modal-view/login-page", "context", function (username: string, password: string) {
console.log(username + "/" + password);
label.text = username + "/" + password;
}, fullscreen, false, stretched);
}

function openModal(page: Page, label: Label, context: string) {
page.showModal("ui-tests-app/modal-view/login-page", context, function (username: string, password: string) {
const result = context + "/" + username + "/" + password;
console.log(result);
label.text = result;
}, false);
}

export function onTapSecondModalInCB(args) {
const page = <Page>args.object.page;
const label = page.getViewById<Label>("label");
page.showModal("ui-tests-app/modal-view/login-page", "First", function (username: string, password: string) {
const result = "First/" + username + "/" + password;
console.log(result);
label.text = result;

// Open second modal in the close callback of the first one.
openModal(page, label, "Second");
});
}

export function onTapSecondModalInTimer(args) {
const page = <Page>args.object.page;
const label = page.getViewById<Label>("label");
openModal(page, label, "First");

// Open second modal 1s after the first one.
setTimeout(() => openModal(page, label, "Second"), 1000);
}
4 changes: 4 additions & 0 deletions apps/app/ui-tests-app/modal-view/modal-view.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
<Button text="Login (pop-up)" tap="onTap" />
<Button text="Login (full-screen)" tap="onTap" />
<Button text="Login (pop-up-stretched)" tap="onTapStretched" />

<Button text="Login (second modal in cb)" tap="onTapSecondModalInCB" />
<Button text="Login (second modal in timer)" tap="onTapSecondModalInTimer" />

<Label id="label" text="Anonymous"/>
</StackLayout>
</Page>
2 changes: 1 addition & 1 deletion tests/app/ui/page/page-tests-common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -738,6 +738,7 @@ export function test_WhenPageIsNavigatedToItCanShowAnotherPageAsModal() {
TKUnit.assertTrue(ctx.shownModally, "Modal-page must be shown!");
TKUnit.assertEqual(returnValue, "return value", "Modal-page must return value!");
modalClosed = true;
TKUnit.assertNull(masterPage.modal, "currentPage.modal should be undefined when no modal page is shown!");
}

let modalPage: Page;
Expand All @@ -758,7 +759,6 @@ export function test_WhenPageIsNavigatedToItCanShowAnotherPageAsModal() {
const onModalUnloaded = function (args: EventData) {
modalUnloaded++;
modalPage.off(Page.unloadedEvent, onModalUnloaded);
TKUnit.assertNull(masterPage.modal, "currentPage.modal should be undefined when no modal page is shown!");
}

const navigatedToEventHandler = function (args) {
Expand Down
1 change: 0 additions & 1 deletion tests/app/ui/page/page-tests.ios.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ export function test_WhenShowingModalPageUnloadedIsNotFiredForTheMasterPage() {
let onModalUnloaded = function (args: EventData) {
modalUnloaded++;
modalPage.off(Page.unloadedEvent, onModalUnloaded);
TKUnit.assertNull(masterPage.modal, "currentPage.modal should be undefined when no modal page is shown!");
}

var navigatedToEventHandler = function (args) {
Expand Down
34 changes: 18 additions & 16 deletions tns-core-modules/ui/core/view/view-common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -225,10 +225,10 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition {
const animated = arguments[4];
const stretched = arguments[5];

const view: ViewDefinition = firstAgrument instanceof ViewCommon
? firstAgrument : createViewFromEntry({ moduleName: firstAgrument });
const view = firstAgrument instanceof ViewCommon
? firstAgrument : <ViewCommon>createViewFromEntry({ moduleName: firstAgrument });

(<ViewCommon>view)._showNativeModalView(this, context, closeCallback, fullscreen, animated, stretched);
view._showNativeModalView(this, context, closeCallback, fullscreen, animated, stretched);
return view;
}
}
Expand Down Expand Up @@ -256,27 +256,29 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition {
this._modalParent = parent;
this._modalContext = context;
const that = this;
this._closeModalCallback = function () {
this._closeModalCallback = function (...originalArgs) {
if (that._closeModalCallback) {
const modalIndex = _rootModalViews.indexOf(that);
_rootModalViews.splice(modalIndex);
that._hideNativeModalView(parent);
that._modalParent = null;
that._modalContext = null;
that._closeModalCallback = null;
that._dialogClosed();
parent._modal = null;

if (typeof closeCallback === "function") {
closeCallback.apply(undefined, arguments);

const whenClosedCallback = () => {
that._modalParent = null;
that._modalContext = null;
that._closeModalCallback = null;
that._dialogClosed();
parent._modal = null;

if (typeof closeCallback === "function") {
closeCallback.apply(undefined, originalArgs);
}
}

that._hideNativeModalView(parent, whenClosedCallback);
}
};
}

protected _hideNativeModalView(parent: ViewCommon) {
//
}
protected abstract _hideNativeModalView(parent: ViewCommon, whenClosedCallback: () => void);

protected _raiseLayoutChangedEvent() {
const args: EventData = {
Expand Down
4 changes: 2 additions & 2 deletions tns-core-modules/ui/core/view/view.android.ts
Original file line number Diff line number Diff line change
Expand Up @@ -613,14 +613,14 @@ export class View extends ViewCommon {
this._dialogFragment.show(parent._getRootFragmentManager(), this._domId.toString());
}

protected _hideNativeModalView(parent: View) {
protected _hideNativeModalView(parent: View, whenClosedCallback: () => void) {
const manager = this._dialogFragment.getFragmentManager();
if (manager) {
this._dialogFragment.dismissAllowingStateLoss();
}

this._dialogFragment = null;
super._hideNativeModalView(parent);
whenClosedCallback();
}

[isEnabledProperty.setNative](value: boolean) {
Expand Down
17 changes: 11 additions & 6 deletions tns-core-modules/ui/core/view/view.ios.ts
Original file line number Diff line number Diff line change
Expand Up @@ -380,8 +380,14 @@ export class View extends ViewCommon {
}

const parentController = parentWithController.viewController;
if (parentController.presentedViewController) {
traceWrite("Parent is already presenting view controller. Close the current modal page before showing another one!",
traceCategories.ViewHierarchy, traceMessageType.error);
return;
}

if (!parentController.view || !parentController.view.window) {
traceWrite("Parent page is not part of the window hierarchy. Close the current modal page before showing another one!",
traceWrite("Parent page is not part of the window hierarchy.",
traceCategories.ViewHierarchy, traceMessageType.error);
return;
}
Expand Down Expand Up @@ -426,7 +432,7 @@ export class View extends ViewCommon {
}
}

protected _hideNativeModalView(parent: View) {
protected _hideNativeModalView(parent: View, whenClosedCallback: () => void) {
if (!parent || !parent.viewController) {
traceError("Trying to hide modal view but no parent with viewController specified.")
return;
Expand All @@ -435,8 +441,7 @@ export class View extends ViewCommon {
const parentController = parent.viewController;
const animated = (<any>this.viewController).animated;

super._hideNativeModalView(parent);
parentController.dismissModalViewControllerAnimated(animated);
parentController.dismissViewControllerAnimatedCompletion(animated, whenClosedCallback);
}

[isEnabledProperty.getDefault](): boolean {
Expand Down Expand Up @@ -907,11 +912,11 @@ export namespace ios {
const parentPageInsetsTop = parent.nativeViewProtected.safeAreaInsets.top;
const currentInsetsTop = this.view.safeAreaInsets.top;
const additionalInsetsTop = Math.max(parentPageInsetsTop - currentInsetsTop, 0);

const parentPageInsetsBottom = parent.nativeViewProtected.safeAreaInsets.bottom;
const currentInsetsBottom = this.view.safeAreaInsets.bottom;
const additionalInsetsBottom = Math.max(parentPageInsetsBottom - currentInsetsBottom, 0);

if (additionalInsetsTop > 0 || additionalInsetsBottom > 0) {
const additionalInsets = new UIEdgeInsets({ top: additionalInsetsTop, left: 0, bottom: additionalInsetsBottom, right: 0 });
this.additionalSafeAreaInsets = additionalInsets;
Expand Down