Skip to content

Commit 2704915

Browse files
authored
fix(frame): add generic frame cleanup logic after modal dialog close (NativeScript#5479)
1 parent eb76a3b commit 2704915

File tree

7 files changed

+126
-39
lines changed

7 files changed

+126
-39
lines changed
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { NavigatedData } from "tns-core-modules/ui/page";
2+
import { View } from "tns-core-modules/ui/core/view";
3+
import * as TKUnit from "../../TKUnit";
4+
import { stack } from "tns-core-modules/ui/frame";
5+
import { isAndroid } from "tns-core-modules/platform";
6+
7+
export function onNavigatedTo(args: NavigatedData) {
8+
TKUnit.assertEqual(stack().length, 2, "Host and tab modal frame should be instantiated at this point!");
9+
// shownModally raised after page.NavigatedTo on iOS so we close modal there
10+
if (isAndroid) {
11+
(args.object as View).closeModal();
12+
}
13+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<Page backgroundColor="green" navigatedTo="onNavigatedTo">
2+
3+
<ActionBar class="action-bar">
4+
<Label class="action-bar-title" text="Modal"></Label>
5+
</ActionBar>
6+
7+
<Label text="Text" />
8+
</Page>
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { ShownModallyData } from "tns-core-modules/ui/core/view";
2+
import { TabView } from "tns-core-modules/ui/tab-view/tab-view";
3+
import * as TKUnit from "../../TKUnit";
4+
import { stack } from "tns-core-modules/ui/frame";
5+
import { isIOS } from "tns-core-modules/platform"
6+
7+
export function onShownModally(args: ShownModallyData) {
8+
const tabView = <TabView>args.object;
9+
TKUnit.assertNotNull(tabView);
10+
if (args.context) {
11+
args.context.shownModally = true;
12+
}
13+
14+
const hostFrame = stack()[0];
15+
TKUnit.assertNotNull(hostFrame, "Host frame should not be null");
16+
TKUnit.assertEqual(hostFrame.currentPage.modal, tabView, "hostFrame.currentPage.modal should be equal to the tabView instance on tabView.shownModally event handler.");
17+
18+
// shownModally raised after page.NavigatedTo on iOS
19+
if (isIOS) {
20+
args.closeCallback("return value");
21+
}
22+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<TabView androidTabsPosition="bottom" shownModally="onShownModally">
2+
<TabViewItem title="Modal First">
3+
<Frame defaultPage="ui/page/modal-tab-page" />
4+
</TabViewItem>
5+
<TabViewItem>
6+
<Frame />
7+
</TabViewItem>
8+
<TabViewItem title="Modal Second">
9+
<Label text="tab 2" />
10+
</TabViewItem>
11+
</TabView>

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

Lines changed: 66 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import { Frame, stack } from "tns-core-modules/ui/frame";
2323
import { Label } from "tns-core-modules/ui/label";
2424
import { Color } from "tns-core-modules/color";
2525
import { TabView, TabViewItem } from "tns-core-modules/ui/tab-view/tab-view";
26+
import { _resetRootView, getRootView } from "tns-core-modules/application";
2627

2728
export function addLabelToPage(page: Page, text?: string) {
2829
const label = new Label();
@@ -874,6 +875,71 @@ export function test_WhenModalPageShownShowModalEventsRaisedOnRootModalPage() {
874875
TKUnit.assertTrue(shownModallyCount === 1);
875876
}
876877

878+
export function test_WhenModalPageShownShowModalEventsRaisedOnRootModalTabView() {
879+
let showingModallyCount = 0;
880+
let shownModallyCount = 0;
881+
882+
let ready = false;
883+
884+
const modalCloseCallback = function (returnValue: any) {
885+
TKUnit.assertEqual(stack().length, 1, "Single host frame should be instantiated at this point!");
886+
887+
ready = true;
888+
}
889+
890+
const modalTabViewShowingModallyEventHandler = function(args: ShownModallyData) {
891+
showingModallyCount++;
892+
}
893+
894+
const modalTabViewShownModallyEventHandler = function(args: ShownModallyData) {
895+
shownModallyCount++;
896+
}
897+
898+
const hostNavigatedToEventHandler = function(args) {
899+
const page = <Page>args.object;
900+
page.off(Page.navigatedToEvent, hostNavigatedToEventHandler);
901+
902+
const basePath = "ui/page/";
903+
const entry: NavigationEntry = {
904+
moduleName: basePath + "modal-tab-root"
905+
};
906+
907+
TKUnit.assertEqual(stack().length, 1, "Single host frame should be instantiated at this point!");
908+
909+
const modalTabView = createViewFromEntry(entry) as TabView;
910+
modalTabView.on(TabView.showingModallyEvent, modalTabViewShowingModallyEventHandler);
911+
modalTabView.on(TabView.shownModallyEvent, modalTabViewShownModallyEventHandler);
912+
913+
TKUnit.assertEqual(stack().length, 2, "Host and tab modal frame should be instantiated at this point!");
914+
915+
page.showModal(modalTabView, { }, modalCloseCallback, false, false);
916+
}
917+
918+
const masterPageFactory = function (): Page {
919+
const masterPage = new Page();
920+
masterPage.id = "masterPage_test_WhenModalPageShownShowModalEventsRaisedOnRootModalTabView";
921+
masterPage.on(Page.navigatedToEvent, hostNavigatedToEventHandler);
922+
923+
const label = new Label();
924+
label.text = "Text";
925+
masterPage.content = label;
926+
return masterPage;
927+
};
928+
929+
TKUnit.assertEqual(stack().length, 1, "Single host frame should be instantiated at this point!");
930+
931+
helper.navigate(masterPageFactory);
932+
933+
TKUnit.assertEqual(stack().length, 2, "Host and modal tab frame should be instantiated at this point!");
934+
935+
TKUnit.waitUntilReady(() => ready);
936+
937+
TKUnit.assertEqual(stack().length, 1, "Single host frame should be instantiated at this point!");
938+
939+
TKUnit.assertTrue(showingModallyCount === 1);
940+
TKUnit.assertTrue(shownModallyCount === 1);
941+
}
942+
877943
export function test_percent_width_and_height_support() {
878944
const testPage = new Page();
879945
testPage.id = "test_percent_width_and_height_support";
@@ -935,40 +1001,3 @@ export function test_percent_margin_support() {
9351001
TKUnit.assertEqual(bounds.right, parentWidth, "Stack RIGHT position incorrect");
9361002
TKUnit.assertEqual(bounds.bottom, parentHeight, "Stack BOTTOM position incorrect");
9371003
}
938-
939-
//export function test_ModalPage_Layout_is_Correct() {
940-
// const testPage: Page;
941-
// const label: Label;
942-
// const pageFactory = function () {
943-
// testPage = new Page();
944-
// label = new Label();
945-
// label.text = "Will Show modal page";
946-
// testPage.content = label;
947-
// return testPage;
948-
// };
949-
950-
// helper.navigate(pageFactory);
951-
// const basePath = "ui/page/";
952-
// testPage.showModal(basePath + "page21", testPage, () => { }, false);
953-
954-
// // TODO: Remove this once navigate and showModal returns Promise<Page>.
955-
// TKUnit.wait(0.350);
956-
// const childPage = (<any>testPage).childPage;
957-
// const closeCallback: Function = (<any>testPage).close;
958-
959-
// try {
960-
// const layout = <StackLayout>childPage.content;
961-
// const repeater = layout.getChildAt(1);
962-
// TKUnit.assertTrue(repeater.isLayoutValid, "layout should be valid.");
963-
// const bounds = repeater._getCurrentLayoutBounds();
964-
// const height = bounds.bottom - bounds.top;
965-
// TKUnit.assertTrue(height > 0, "Layout should be >0.");
966-
967-
// closeCallback();
968-
// TKUnit.wait(0.150);
969-
// }
970-
// finally {
971-
// helper.goBack
972-
// helper.goBack();
973-
// }
974-
//}

tns-core-modules/ui/core/view-base/view-base.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -959,7 +959,10 @@ export abstract class ViewBase extends Observable implements ViewBaseDefinition
959959
}
960960

961961
public _dialogClosed(): void {
962-
return;
962+
eachDescendant(this, (child: ViewBase) => {
963+
child._dialogClosed();
964+
return true;
965+
});
963966
}
964967

965968
public _onRootViewReset(): void {

tns-core-modules/ui/frame/frame-common.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -435,7 +435,8 @@ export class FrameBase extends CustomLayoutView implements FrameDefinition {
435435
}
436436

437437
public _dialogClosed(): void {
438-
this._popFromFrameStack();
438+
// No super call as we do not support nested frames to clean up
439+
this._removeFromFrameStack();
439440
}
440441

441442
public _onRootViewReset(): void {

0 commit comments

Comments
 (0)