mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-08-15 11:01:21 +08:00
fix(ios-dialogs): unable to show dialog from modal view without a page (#5881)
* fix(ios-dialogs): unable to show dialog from modal view * tests(modal-navigation): add test that opens dialog inside modal view
This commit is contained in:

committed by
GitHub

parent
6d978add18
commit
e59d1567a5
@ -20,6 +20,15 @@ export function onNavigatedFrom(args: NavigatedData) {
|
|||||||
console.log("home-page onNavigatedFrom");
|
console.log("home-page onNavigatedFrom");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function onModalNoPage(args: EventData) {
|
||||||
|
const view = args.object as View;
|
||||||
|
|
||||||
|
view.showModal("modal-no-page/modal-no-page",
|
||||||
|
"context",
|
||||||
|
() => console.log("home-page modal frame closed"),
|
||||||
|
false);
|
||||||
|
}
|
||||||
|
|
||||||
export function onModalFrame(args: EventData) {
|
export function onModalFrame(args: EventData) {
|
||||||
const view = args.object as View;
|
const view = args.object as View;
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
</ActionBar>
|
</ActionBar>
|
||||||
|
|
||||||
<StackLayout>
|
<StackLayout>
|
||||||
|
<Button text="Show Modal Without Page" tap="onModalNoPage" />
|
||||||
<Button text="Show Modal Page With Frame" tap="onModalFrame" />
|
<Button text="Show Modal Page With Frame" tap="onModalFrame" />
|
||||||
<Button text="Show Modal Page" tap="onModalPage" />
|
<Button text="Show Modal Page" tap="onModalPage" />
|
||||||
<Button text="Show Modal Layout" tap="onModalLayout" />
|
<Button text="Show Modal Layout" tap="onModalLayout" />
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
export {
|
export {
|
||||||
|
onModalNoPage,
|
||||||
onModalFrame,
|
onModalFrame,
|
||||||
onModalPage,
|
onModalPage,
|
||||||
onModalLayout,
|
onModalLayout,
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
<StackLayout>
|
<StackLayout>
|
||||||
<Label text="Home" horizontalAlignment="center" />
|
<Label text="Home" horizontalAlignment="center" />
|
||||||
|
<Button text="Show Modal Without Page" tap="onModalNoPage" />
|
||||||
<Button text="Show Modal Page With Frame" tap="onModalFrame" />
|
<Button text="Show Modal Page With Frame" tap="onModalFrame" />
|
||||||
<Button text="Show Modal Page" tap="onModalPage" />
|
<Button text="Show Modal Page" tap="onModalPage" />
|
||||||
<Button text="Show Modal Layout" tap="onModalLayout" />
|
<Button text="Show Modal Layout" tap="onModalLayout" />
|
||||||
|
28
e2e/modal-navigation/app/modal-no-page/modal-no-page.ts
Normal file
28
e2e/modal-navigation/app/modal-no-page/modal-no-page.ts
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import { StackLayout } from "tns-core-modules/ui/layouts/stack-layout";
|
||||||
|
import { NavigatedData, Page } from "tns-core-modules/ui/page";
|
||||||
|
import { View, EventData } from "tns-core-modules/ui/core/view";
|
||||||
|
import { Frame, ShownModallyData } from "tns-core-modules/ui/frame";
|
||||||
|
import { fromObject } from "tns-core-modules/data/observable";
|
||||||
|
import { confirm } from "ui/dialogs";
|
||||||
|
|
||||||
|
export function onLoaded(args) {
|
||||||
|
console.log("modal-no-page loaded");
|
||||||
|
}
|
||||||
|
|
||||||
|
export function closeModal(args: EventData) {
|
||||||
|
(args.object as View).closeModal();
|
||||||
|
}
|
||||||
|
|
||||||
|
export function showDialog(args: EventData) {
|
||||||
|
let options = {
|
||||||
|
title: "Dialog",
|
||||||
|
message: "Message",
|
||||||
|
okButtonText: "Yes",
|
||||||
|
cancelButtonText: "No"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
confirm(options).then((result: boolean) => {
|
||||||
|
console.log(result);
|
||||||
|
})
|
||||||
|
}
|
4
e2e/modal-navigation/app/modal-no-page/modal-no-page.xml
Normal file
4
e2e/modal-navigation/app/modal-no-page/modal-no-page.xml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<StackLayout backgroundColor="lightGreen" loaded="onLoaded">
|
||||||
|
<Button text="Show Dialog" tap="showDialog"/>
|
||||||
|
<Button text="Close Modal" tap="closeModal" />
|
||||||
|
</StackLayout>
|
@ -3,6 +3,7 @@ import { NavigatedData, Page } from "tns-core-modules/ui/page";
|
|||||||
import { View, EventData } from "tns-core-modules/ui/core/view";
|
import { View, EventData } from "tns-core-modules/ui/core/view";
|
||||||
import { Frame, ShownModallyData } from "tns-core-modules/ui/frame";
|
import { Frame, ShownModallyData } from "tns-core-modules/ui/frame";
|
||||||
import { fromObject } from "tns-core-modules/data/observable";
|
import { fromObject } from "tns-core-modules/data/observable";
|
||||||
|
import { confirm } from "ui/dialogs";
|
||||||
|
|
||||||
export function onShowingModally(args: ShownModallyData) {
|
export function onShowingModally(args: ShownModallyData) {
|
||||||
console.log("modal-page showingModally");
|
console.log("modal-page showingModally");
|
||||||
@ -64,4 +65,18 @@ export function onNavigate(args: EventData) {
|
|||||||
const view = args.object as View;
|
const view = args.object as View;
|
||||||
const page = view.page as Page;
|
const page = view.page as Page;
|
||||||
page.frame.navigate("modal-second/modal-second-page");
|
page.frame.navigate("modal-second/modal-second-page");
|
||||||
|
}
|
||||||
|
|
||||||
|
export function showDialog(args: EventData) {
|
||||||
|
let options = {
|
||||||
|
title: "Dialog",
|
||||||
|
message: "Message",
|
||||||
|
okButtonText: "Yes",
|
||||||
|
cancelButtonText: "No"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
confirm(options).then((result: boolean) => {
|
||||||
|
console.log(result);
|
||||||
|
})
|
||||||
}
|
}
|
@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
<StackLayout backgroundColor="lightGreen">
|
<StackLayout backgroundColor="lightGreen">
|
||||||
<Button text="Navigate To Second Page" tap="onNavigate" visibility="{{ navigationVisibility }}" />
|
<Button text="Navigate To Second Page" tap="onNavigate" visibility="{{ navigationVisibility }}" />
|
||||||
|
<Button text="Show Dialog" tap="showDialog" />
|
||||||
<Button text="Show Nested Modal Page With Frame" tap="showNestedModalFrame" />
|
<Button text="Show Nested Modal Page With Frame" tap="showNestedModalFrame" />
|
||||||
<Button text="Show Nested Modal Page" tap="showNestedModalPage" />
|
<Button text="Show Nested Modal Page" tap="showNestedModalPage" />
|
||||||
<Button text="Close Modal" tap="closeModal" />
|
<Button text="Close Modal" tap="closeModal" />
|
||||||
|
1
tns-core-modules/ui/core/view/view.d.ts
vendored
1
tns-core-modules/ui/core/view/view.d.ts
vendored
@ -775,6 +775,7 @@ export const isEnabledProperty: Property<View, boolean>;
|
|||||||
export const isUserInteractionEnabledProperty: Property<View, boolean>;
|
export const isUserInteractionEnabledProperty: Property<View, boolean>;
|
||||||
|
|
||||||
export namespace ios {
|
export namespace ios {
|
||||||
|
export function getParentWithViewController(parent: View): View
|
||||||
export function isContentScrollable(controller: any /* UIViewController */, owner: View): boolean
|
export function isContentScrollable(controller: any /* UIViewController */, owner: View): boolean
|
||||||
export function updateAutoAdjustScrollInsets(controller: any /* UIViewController */, owner: View): void
|
export function updateAutoAdjustScrollInsets(controller: any /* UIViewController */, owner: View): void
|
||||||
export function updateConstraints(controller: any /* UIViewController */, owner: View): void;
|
export function updateConstraints(controller: any /* UIViewController */, owner: View): void;
|
||||||
|
@ -308,18 +308,8 @@ export class View extends ViewCommon {
|
|||||||
return this._suspendCATransaction || this._suspendNativeUpdatesCount;
|
return this._suspendCATransaction || this._suspendNativeUpdatesCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
private getParentWithViewController(parent: View): View {
|
|
||||||
let view = parent;
|
|
||||||
let controller = view.viewController;
|
|
||||||
while (!controller) {
|
|
||||||
view = view.parent as View;
|
|
||||||
controller = view.viewController;
|
|
||||||
}
|
|
||||||
|
|
||||||
return view;
|
|
||||||
}
|
|
||||||
protected _showNativeModalView(parent: View, context: any, closeCallback: Function, fullscreen?: boolean, animated?: boolean, stretched?: boolean) {
|
protected _showNativeModalView(parent: View, context: any, closeCallback: Function, fullscreen?: boolean, animated?: boolean, stretched?: boolean) {
|
||||||
let parentWithController = this.getParentWithViewController(parent);
|
let parentWithController = ios.getParentWithViewController(parent);
|
||||||
|
|
||||||
super._showNativeModalView(parentWithController, context, closeCallback, fullscreen, stretched);
|
super._showNativeModalView(parentWithController, context, closeCallback, fullscreen, stretched);
|
||||||
let controller = this.viewController;
|
let controller = this.viewController;
|
||||||
@ -592,6 +582,17 @@ export class CustomLayoutView extends View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export namespace ios {
|
export namespace ios {
|
||||||
|
export function getParentWithViewController(parent: View): View {
|
||||||
|
let view = parent;
|
||||||
|
let controller = view.viewController;
|
||||||
|
while (!controller) {
|
||||||
|
view = view.parent as View;
|
||||||
|
controller = view.viewController;
|
||||||
|
}
|
||||||
|
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
export function isContentScrollable(controller: UIViewController, owner: View): boolean {
|
export function isContentScrollable(controller: UIViewController, owner: View): boolean {
|
||||||
let scrollableContent = (<any>owner).scrollableContent;
|
let scrollableContent = (<any>owner).scrollableContent;
|
||||||
if (scrollableContent === undefined) {
|
if (scrollableContent === undefined) {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* iOS specific dialogs functions implementation.
|
* iOS specific dialogs functions implementation.
|
||||||
*/
|
*/
|
||||||
|
import { View, ios as iosView } from "../core/view";
|
||||||
import { ConfirmOptions, PromptOptions, PromptResult, LoginOptions, LoginResult, ActionOptions } from ".";
|
import { ConfirmOptions, PromptOptions, PromptResult, LoginOptions, LoginResult, ActionOptions } from ".";
|
||||||
import { getCurrentPage, getLabelColor, getButtonColors, getTextFieldColor, isDialogOptions, inputType, ALERT, OK, CONFIRM, CANCEL, PROMPT, LOGIN } from "./dialogs-common";
|
import { getCurrentPage, getLabelColor, getButtonColors, getTextFieldColor, isDialogOptions, inputType, ALERT, OK, CONFIRM, CANCEL, PROMPT, LOGIN } from "./dialogs-common";
|
||||||
import { isString, isDefined, isFunction } from "../../utils/types";
|
import { isString, isDefined, isFunction } from "../../utils/types";
|
||||||
@ -42,7 +42,7 @@ export function alert(arg: any): Promise<void> {
|
|||||||
try {
|
try {
|
||||||
let options = !isDialogOptions(arg) ? { title: ALERT, okButtonText: OK, message: arg + "" } : arg;
|
let options = !isDialogOptions(arg) ? { title: ALERT, okButtonText: OK, message: arg + "" } : arg;
|
||||||
let alertController = UIAlertController.alertControllerWithTitleMessagePreferredStyle(options.title, options.message, UIAlertControllerStyle.Alert);
|
let alertController = UIAlertController.alertControllerWithTitleMessagePreferredStyle(options.title, options.message, UIAlertControllerStyle.Alert);
|
||||||
|
|
||||||
addButtonsToAlertController(alertController, options, () => { resolve(); });
|
addButtonsToAlertController(alertController, options, () => { resolve(); });
|
||||||
|
|
||||||
showUIAlertController(alertController);
|
showUIAlertController(alertController);
|
||||||
@ -157,7 +157,7 @@ export function login(): Promise<LoginResult> {
|
|||||||
let alertController = UIAlertController.alertControllerWithTitleMessagePreferredStyle(options.title, options.message, UIAlertControllerStyle.Alert);
|
let alertController = UIAlertController.alertControllerWithTitleMessagePreferredStyle(options.title, options.message, UIAlertControllerStyle.Alert);
|
||||||
|
|
||||||
let textFieldColor = getTextFieldColor();
|
let textFieldColor = getTextFieldColor();
|
||||||
|
|
||||||
alertController.addTextFieldWithConfigurationHandler((arg: UITextField) => {
|
alertController.addTextFieldWithConfigurationHandler((arg: UITextField) => {
|
||||||
arg.placeholder = "Login";
|
arg.placeholder = "Login";
|
||||||
arg.text = isString(options.userName) ? options.userName : "";
|
arg.text = isString(options.userName) ? options.userName : "";
|
||||||
@ -185,7 +185,7 @@ export function login(): Promise<LoginResult> {
|
|||||||
resolve({
|
resolve({
|
||||||
result: r,
|
result: r,
|
||||||
userName:
|
userName:
|
||||||
userNameTextField.text,
|
userNameTextField.text,
|
||||||
password: passwordTextField.text
|
password: passwordTextField.text
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -200,7 +200,19 @@ export function login(): Promise<LoginResult> {
|
|||||||
function showUIAlertController(alertController: UIAlertController) {
|
function showUIAlertController(alertController: UIAlertController) {
|
||||||
let currentPage = getCurrentPage();
|
let currentPage = getCurrentPage();
|
||||||
if (currentPage) {
|
if (currentPage) {
|
||||||
let viewController: UIViewController = currentPage.modal ? currentPage.modal.ios : currentPage.ios;
|
let view: View = currentPage;
|
||||||
|
let viewController: UIViewController = currentPage.ios;
|
||||||
|
|
||||||
|
if (currentPage.modal) {
|
||||||
|
view = currentPage.modal;
|
||||||
|
|
||||||
|
if (view.ios instanceof UIViewController) {
|
||||||
|
viewController = view.ios;
|
||||||
|
} else {
|
||||||
|
viewController = iosView.getParentWithViewController(view).viewController;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (viewController) {
|
if (viewController) {
|
||||||
if (alertController.popoverPresentationController) {
|
if (alertController.popoverPresentationController) {
|
||||||
alertController.popoverPresentationController.sourceView = viewController.view;
|
alertController.popoverPresentationController.sourceView = viewController.view;
|
||||||
|
Reference in New Issue
Block a user