mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-11-05 13:26:48 +08:00
fix(frame): add generic frame cleanup logic after modal dialog close (#5479)
This commit is contained in:
13
tests/app/ui/page/modal-tab-page.ts
Normal file
13
tests/app/ui/page/modal-tab-page.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { NavigatedData } from "tns-core-modules/ui/page";
|
||||
import { View } from "tns-core-modules/ui/core/view";
|
||||
import * as TKUnit from "../../TKUnit";
|
||||
import { stack } from "tns-core-modules/ui/frame";
|
||||
import { isAndroid } from "tns-core-modules/platform";
|
||||
|
||||
export function onNavigatedTo(args: NavigatedData) {
|
||||
TKUnit.assertEqual(stack().length, 2, "Host and tab modal frame should be instantiated at this point!");
|
||||
// shownModally raised after page.NavigatedTo on iOS so we close modal there
|
||||
if (isAndroid) {
|
||||
(args.object as View).closeModal();
|
||||
}
|
||||
}
|
||||
8
tests/app/ui/page/modal-tab-page.xml
Normal file
8
tests/app/ui/page/modal-tab-page.xml
Normal file
@@ -0,0 +1,8 @@
|
||||
<Page backgroundColor="green" navigatedTo="onNavigatedTo">
|
||||
|
||||
<ActionBar class="action-bar">
|
||||
<Label class="action-bar-title" text="Modal"></Label>
|
||||
</ActionBar>
|
||||
|
||||
<Label text="Text" />
|
||||
</Page>
|
||||
22
tests/app/ui/page/modal-tab-root.ts
Normal file
22
tests/app/ui/page/modal-tab-root.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { ShownModallyData } from "tns-core-modules/ui/core/view";
|
||||
import { TabView } from "tns-core-modules/ui/tab-view/tab-view";
|
||||
import * as TKUnit from "../../TKUnit";
|
||||
import { stack } from "tns-core-modules/ui/frame";
|
||||
import { isIOS } from "tns-core-modules/platform"
|
||||
|
||||
export function onShownModally(args: ShownModallyData) {
|
||||
const tabView = <TabView>args.object;
|
||||
TKUnit.assertNotNull(tabView);
|
||||
if (args.context) {
|
||||
args.context.shownModally = true;
|
||||
}
|
||||
|
||||
const hostFrame = stack()[0];
|
||||
TKUnit.assertNotNull(hostFrame, "Host frame should not be null");
|
||||
TKUnit.assertEqual(hostFrame.currentPage.modal, tabView, "hostFrame.currentPage.modal should be equal to the tabView instance on tabView.shownModally event handler.");
|
||||
|
||||
// shownModally raised after page.NavigatedTo on iOS
|
||||
if (isIOS) {
|
||||
args.closeCallback("return value");
|
||||
}
|
||||
}
|
||||
11
tests/app/ui/page/modal-tab-root.xml
Normal file
11
tests/app/ui/page/modal-tab-root.xml
Normal file
@@ -0,0 +1,11 @@
|
||||
<TabView androidTabsPosition="bottom" shownModally="onShownModally">
|
||||
<TabViewItem title="Modal First">
|
||||
<Frame defaultPage="ui/page/modal-tab-page" />
|
||||
</TabViewItem>
|
||||
<TabViewItem>
|
||||
<Frame />
|
||||
</TabViewItem>
|
||||
<TabViewItem title="Modal Second">
|
||||
<Label text="tab 2" />
|
||||
</TabViewItem>
|
||||
</TabView>
|
||||
@@ -23,6 +23,7 @@ import { Frame, stack } from "tns-core-modules/ui/frame";
|
||||
import { Label } from "tns-core-modules/ui/label";
|
||||
import { Color } from "tns-core-modules/color";
|
||||
import { TabView, TabViewItem } from "tns-core-modules/ui/tab-view/tab-view";
|
||||
import { _resetRootView, getRootView } from "tns-core-modules/application";
|
||||
|
||||
export function addLabelToPage(page: Page, text?: string) {
|
||||
const label = new Label();
|
||||
@@ -874,6 +875,71 @@ export function test_WhenModalPageShownShowModalEventsRaisedOnRootModalPage() {
|
||||
TKUnit.assertTrue(shownModallyCount === 1);
|
||||
}
|
||||
|
||||
export function test_WhenModalPageShownShowModalEventsRaisedOnRootModalTabView() {
|
||||
let showingModallyCount = 0;
|
||||
let shownModallyCount = 0;
|
||||
|
||||
let ready = false;
|
||||
|
||||
const modalCloseCallback = function (returnValue: any) {
|
||||
TKUnit.assertEqual(stack().length, 1, "Single host frame should be instantiated at this point!");
|
||||
|
||||
ready = true;
|
||||
}
|
||||
|
||||
const modalTabViewShowingModallyEventHandler = function(args: ShownModallyData) {
|
||||
showingModallyCount++;
|
||||
}
|
||||
|
||||
const modalTabViewShownModallyEventHandler = function(args: ShownModallyData) {
|
||||
shownModallyCount++;
|
||||
}
|
||||
|
||||
const hostNavigatedToEventHandler = function(args) {
|
||||
const page = <Page>args.object;
|
||||
page.off(Page.navigatedToEvent, hostNavigatedToEventHandler);
|
||||
|
||||
const basePath = "ui/page/";
|
||||
const entry: NavigationEntry = {
|
||||
moduleName: basePath + "modal-tab-root"
|
||||
};
|
||||
|
||||
TKUnit.assertEqual(stack().length, 1, "Single host frame should be instantiated at this point!");
|
||||
|
||||
const modalTabView = createViewFromEntry(entry) as TabView;
|
||||
modalTabView.on(TabView.showingModallyEvent, modalTabViewShowingModallyEventHandler);
|
||||
modalTabView.on(TabView.shownModallyEvent, modalTabViewShownModallyEventHandler);
|
||||
|
||||
TKUnit.assertEqual(stack().length, 2, "Host and tab modal frame should be instantiated at this point!");
|
||||
|
||||
page.showModal(modalTabView, { }, modalCloseCallback, false, false);
|
||||
}
|
||||
|
||||
const masterPageFactory = function (): Page {
|
||||
const masterPage = new Page();
|
||||
masterPage.id = "masterPage_test_WhenModalPageShownShowModalEventsRaisedOnRootModalTabView";
|
||||
masterPage.on(Page.navigatedToEvent, hostNavigatedToEventHandler);
|
||||
|
||||
const label = new Label();
|
||||
label.text = "Text";
|
||||
masterPage.content = label;
|
||||
return masterPage;
|
||||
};
|
||||
|
||||
TKUnit.assertEqual(stack().length, 1, "Single host frame should be instantiated at this point!");
|
||||
|
||||
helper.navigate(masterPageFactory);
|
||||
|
||||
TKUnit.assertEqual(stack().length, 2, "Host and modal tab frame should be instantiated at this point!");
|
||||
|
||||
TKUnit.waitUntilReady(() => ready);
|
||||
|
||||
TKUnit.assertEqual(stack().length, 1, "Single host frame should be instantiated at this point!");
|
||||
|
||||
TKUnit.assertTrue(showingModallyCount === 1);
|
||||
TKUnit.assertTrue(shownModallyCount === 1);
|
||||
}
|
||||
|
||||
export function test_percent_width_and_height_support() {
|
||||
const testPage = new Page();
|
||||
testPage.id = "test_percent_width_and_height_support";
|
||||
@@ -935,40 +1001,3 @@ export function test_percent_margin_support() {
|
||||
TKUnit.assertEqual(bounds.right, parentWidth, "Stack RIGHT position incorrect");
|
||||
TKUnit.assertEqual(bounds.bottom, parentHeight, "Stack BOTTOM position incorrect");
|
||||
}
|
||||
|
||||
//export function test_ModalPage_Layout_is_Correct() {
|
||||
// const testPage: Page;
|
||||
// const label: Label;
|
||||
// const pageFactory = function () {
|
||||
// testPage = new Page();
|
||||
// label = new Label();
|
||||
// label.text = "Will Show modal page";
|
||||
// testPage.content = label;
|
||||
// return testPage;
|
||||
// };
|
||||
|
||||
// helper.navigate(pageFactory);
|
||||
// const basePath = "ui/page/";
|
||||
// testPage.showModal(basePath + "page21", testPage, () => { }, false);
|
||||
|
||||
// // TODO: Remove this once navigate and showModal returns Promise<Page>.
|
||||
// TKUnit.wait(0.350);
|
||||
// const childPage = (<any>testPage).childPage;
|
||||
// const closeCallback: Function = (<any>testPage).close;
|
||||
|
||||
// try {
|
||||
// const layout = <StackLayout>childPage.content;
|
||||
// const repeater = layout.getChildAt(1);
|
||||
// TKUnit.assertTrue(repeater.isLayoutValid, "layout should be valid.");
|
||||
// const bounds = repeater._getCurrentLayoutBounds();
|
||||
// const height = bounds.bottom - bounds.top;
|
||||
// TKUnit.assertTrue(height > 0, "Layout should be >0.");
|
||||
|
||||
// closeCallback();
|
||||
// TKUnit.wait(0.150);
|
||||
// }
|
||||
// finally {
|
||||
// helper.goBack
|
||||
// helper.goBack();
|
||||
// }
|
||||
//}
|
||||
@@ -959,7 +959,10 @@ export abstract class ViewBase extends Observable implements ViewBaseDefinition
|
||||
}
|
||||
|
||||
public _dialogClosed(): void {
|
||||
return;
|
||||
eachDescendant(this, (child: ViewBase) => {
|
||||
child._dialogClosed();
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
public _onRootViewReset(): void {
|
||||
|
||||
@@ -435,7 +435,8 @@ export class FrameBase extends CustomLayoutView implements FrameDefinition {
|
||||
}
|
||||
|
||||
public _dialogClosed(): void {
|
||||
this._popFromFrameStack();
|
||||
// No super call as we do not support nested frames to clean up
|
||||
this._removeFromFrameStack();
|
||||
}
|
||||
|
||||
public _onRootViewReset(): void {
|
||||
|
||||
Reference in New Issue
Block a user