FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

feat(modals): Enable modal dialog chaining in IOS (#6637) · NativeScript/NativeScript@64bccb9 · GitHub

Commit 64bccb9

Browse files
authored andcommitted
feat(modals): Enable modal dialog chaining in IOS (#6637)
* feat(modals): fire close callback after close in IOS * chore(tests): Fix some test depending on the order of events
1 parent bc68773 commit 64bccb9

9 files changed

Lines changed: 91 additions & 51 deletions

File tree

Lines changed: 17 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,29 @@
1-
import * as pages from "tns-core-modules/ui/page";
2-
import * as textField from "tns-core-modules/ui/text-field";
3-
import * as observable from "tns-core-modules/data/observable";
1+
import { Page, ShownModallyData } from "tns-core-modules/ui/page";
2+
import { EventData, fromObject } from "tns-core-modules/data/observable";
43

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

8-
var page: pages.Page;
9-
var usernameTextField: textField.TextField;
10-
var passwordTextField: textField.TextField;
8+
page.bindingContext = fromObject({
9+
username: "username",
10+
password: "password",
11+
context: args.context,
12+
onLoginButtonTap: function() {
13+
console.log("login-page.onLoginButtonTap");
14+
args.closeCallback(this.username, this.password);
15+
}
16+
})
17+
}
1118

12-
export function onShownModally(args: pages.ShownModallyData) {
19+
export function onShownModally(args: ShownModallyData) {
1320
console.log("login-page.onShownModally, context: " + args.context);
14-
context = args.context;
15-
closeCallback = args.closeCallback;
1621
}
1722

18-
export function onLoaded(args: observable.EventData) {
23+
export function onLoaded(args: EventData) {
1924
console.log("login-page.onLoaded");
20-
page = <pages.Page>args.object;
21-
usernameTextField = page.getViewById<textField.TextField>("username");
22-
passwordTextField = page.getViewById<textField.TextField>("password");
2325
}
2426

2527
export function onUnloaded() {
2628
console.log("login-page.onUnloaded");
2729
}
28-
29-
export function onLoginButtonTap() {
30-
console.log("login-page.onLoginButtonTap");
31-
closeCallback(usernameTextField.text, passwordTextField.text);
32-
}
Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1-
<Page xmlns="http://schemas.nativescript.org/tns.xsd" shownModally="onShownModally"
1+
<Page xmlns="http://schemas.nativescript.org/tns.xsd"
2+
showingModally="onShowingModally"
3+
shownModally="onShownModally"
24
loaded="onLoaded" unloaded="onUnloaded" backgroundColor="Red">
35
<StackLayout backgroundColor="PaleGreen" margin="10">
4-
<TextField hint="username" id="username" text="username"/>
5-
<TextField hint="password" id="password" text="password" secure="true"/>
6-
<Button text="Login" tap="onLoginButtonTap"/>
6+
<Label text="{{ context }}"/>
7+
<TextField hint="username" text="{{ username }}"/>
8+
<TextField hint="password" text="{{ password }}" secure="true"/>
9+
<Button text="Login" tap="{{ onLoginButtonTap }}"/>
710
</StackLayout>
811
</Page>

‎apps/app/ui-tests-app/modal-view/modal-view.ts‎

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,39 @@ export function onTapStretched(args) {
1616
const label = page.getViewById<Label>("label");
1717
var fullscreen = false;
1818
var stretched = true;
19-
19+
2020
page.showModal("ui-tests-app/modal-view/login-page", "context", function (username: string, password: string) {
2121
console.log(username + "/" + password);
2222
label.text = username + "/" + password;
2323
}, fullscreen, false, stretched);
2424
}
25+
26+
function openModal(page: Page, label: Label, context: string) {
27+
page.showModal("ui-tests-app/modal-view/login-page", context, function (username: string, password: string) {
28+
const result = context + "/" + username + "/" + password;
29+
console.log(result);
30+
label.text = result;
31+
}, false);
32+
}
33+
34+
export function onTapSecondModalInCB(args) {
35+
const page = <Page>args.object.page;
36+
const label = page.getViewById<Label>("label");
37+
page.showModal("ui-tests-app/modal-view/login-page", "First", function (username: string, password: string) {
38+
const result = "First/" + username + "/" + password;
39+
console.log(result);
40+
label.text = result;
41+
42+
// Open second modal in the close callback of the first one.
43+
openModal(page, label, "Second");
44+
});
45+
}
46+
47+
export function onTapSecondModalInTimer(args) {
48+
const page = <Page>args.object.page;
49+
const label = page.getViewById<Label>("label");
50+
openModal(page, label, "First");
51+
52+
// Open second modal 1s after the first one.
53+
setTimeout(() => openModal(page, label, "Second"), 1000);
54+
}

‎apps/app/ui-tests-app/modal-view/modal-view.xml‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33
<Button text="Login (pop-up)" tap="onTap" />
44
<Button text="Login (full-screen)" tap="onTap" />
55
<Button text="Login (pop-up-stretched)" tap="onTapStretched" />
6+
7+
<Button text="Login (second modal in cb)" tap="onTapSecondModalInCB" />
8+
<Button text="Login (second modal in timer)" tap="onTapSecondModalInTimer" />
9+
610
<Label id="label" text="Anonymous"/>
711
</StackLayout>
812
</Page>

‎tests/app/ui/page/page-tests-common.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -738,6 +738,7 @@ export function test_WhenPageIsNavigatedToItCanShowAnotherPageAsModal() {
738738
TKUnit.assertTrue(ctx.shownModally, "Modal-page must be shown!");
739739
TKUnit.assertEqual(returnValue, "return value", "Modal-page must return value!");
740740
modalClosed = true;
741+
TKUnit.assertNull(masterPage.modal, "currentPage.modal should be undefined when no modal page is shown!");
741742
}
742743

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

764764
const navigatedToEventHandler = function (args) {

‎tests/app/ui/page/page-tests.ios.ts‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ export function test_WhenShowingModalPageUnloadedIsNotFiredForTheMasterPage() {
3737
let onModalUnloaded = function (args: EventData) {
3838
modalUnloaded++;
3939
modalPage.off(Page.unloadedEvent, onModalUnloaded);
40-
TKUnit.assertNull(masterPage.modal, "currentPage.modal should be undefined when no modal page is shown!");
4140
}
4241

4342
var navigatedToEventHandler = function (args) {

‎tns-core-modules/ui/core/view/view-common.ts‎

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -225,10 +225,10 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition {
225225
const animated = arguments[4];
226226
const stretched = arguments[5];
227227

228-
const view: ViewDefinition = firstAgrument instanceof ViewCommon
229-
? firstAgrument : createViewFromEntry({ moduleName: firstAgrument });
228+
const view = firstAgrument instanceof ViewCommon
229+
? firstAgrument : <ViewCommon>createViewFromEntry({ moduleName: firstAgrument });
230230

231-
(<ViewCommon>view)._showNativeModalView(this, context, closeCallback, fullscreen, animated, stretched);
231+
view._showNativeModalView(this, context, closeCallback, fullscreen, animated, stretched);
232232
return view;
233233
}
234234
}
@@ -256,27 +256,29 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition {
256256
this._modalParent = parent;
257257
this._modalContext = context;
258258
const that = this;
259-
this._closeModalCallback = function () {
259+
this._closeModalCallback = function (...originalArgs) {
260260
if (that._closeModalCallback) {
261261
const modalIndex = _rootModalViews.indexOf(that);
262262
_rootModalViews.splice(modalIndex);
263-
that._hideNativeModalView(parent);
264-
that._modalParent = null;
265-
that._modalContext = null;
266-
that._closeModalCallback = null;
267-
that._dialogClosed();
268-
parent._modal = null;
269-
270-
if (typeof closeCallback === "function") {
271-
closeCallback.apply(undefined, arguments);
263+
264+
const whenClosedCallback = () => {
265+
that._modalParent = null;
266+
that._modalContext = null;
267+
that._closeModalCallback = null;
268+
that._dialogClosed();
269+
parent._modal = null;
270+
271+
if (typeof closeCallback === "function") {
272+
closeCallback.apply(undefined, originalArgs);
273+
}
272274
}
275+
276+
that._hideNativeModalView(parent, whenClosedCallback);
273277
}
274278
};
275279
}
276280

277-
protected _hideNativeModalView(parent: ViewCommon) {
278-
//
279-
}
281+
protected abstract _hideNativeModalView(parent: ViewCommon, whenClosedCallback: () => void);
280282

281283
protected _raiseLayoutChangedEvent() {
282284
const args: EventData = {

‎tns-core-modules/ui/core/view/view.android.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -613,14 +613,14 @@ export class View extends ViewCommon {
613613
this._dialogFragment.show(parent._getRootFragmentManager(), this._domId.toString());
614614
}
615615

616-
protected _hideNativeModalView(parent: View) {
616+
protected _hideNativeModalView(parent: View, whenClosedCallback: () => void) {
617617
const manager = this._dialogFragment.getFragmentManager();
618618
if (manager) {
619619
this._dialogFragment.dismissAllowingStateLoss();
620620
}
621621

622622
this._dialogFragment = null;
623-
super._hideNativeModalView(parent);
623+
whenClosedCallback();
624624
}
625625

626626
[isEnabledProperty.setNative](value: boolean) {

‎tns-core-modules/ui/core/view/view.ios.ts‎

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -380,8 +380,14 @@ export class View extends ViewCommon {
380380
}
381381

382382
const parentController = parentWithController.viewController;
383+
if (parentController.presentedViewController) {
384+
traceWrite("Parent is already presenting view controller. Close the current modal page before showing another one!",
385+
traceCategories.ViewHierarchy, traceMessageType.error);
386+
return;
387+
}
388+
383389
if (!parentController.view || !parentController.view.window) {
384-
traceWrite("Parent page is not part of the window hierarchy. Close the current modal page before showing another one!",
390+
traceWrite("Parent page is not part of the window hierarchy.",
385391
traceCategories.ViewHierarchy, traceMessageType.error);
386392
return;
387393
}
@@ -426,7 +432,7 @@ export class View extends ViewCommon {
426432
}
427433
}
428434

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

438-
super._hideNativeModalView(parent);
439-
parentController.dismissModalViewControllerAnimated(animated);
444+
parentController.dismissViewControllerAnimatedCompletion(animated, whenClosedCallback);
440445
}
441446

442447
[isEnabledProperty.getDefault](): boolean {
@@ -907,11 +912,11 @@ export namespace ios {
907912
const parentPageInsetsTop = parent.nativeViewProtected.safeAreaInsets.top;
908913
const currentInsetsTop = this.view.safeAreaInsets.top;
909914
const additionalInsetsTop = Math.max(parentPageInsetsTop - currentInsetsTop, 0);
910-
915+
911916
const parentPageInsetsBottom = parent.nativeViewProtected.safeAreaInsets.bottom;
912917
const currentInsetsBottom = this.view.safeAreaInsets.bottom;
913918
const additionalInsetsBottom = Math.max(parentPageInsetsBottom - currentInsetsBottom, 0);
914-
919+
915920
if (additionalInsetsTop > 0 || additionalInsetsBottom > 0) {
916921
const additionalInsets = new UIEdgeInsets({ top: additionalInsetsTop, left: 0, bottom: additionalInsetsBottom, right: 0 });
917922
this.additionalSafeAreaInsets = additionalInsets;

0 commit comments

Comments
 (0)

Back | FazBrowse Home | New Git URL