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:
Alexander Djenkov
2018-05-29 18:06:02 +03:00
committed by GitHub
parent 6d978add18
commit e59d1567a5
11 changed files with 90 additions and 16 deletions

View File

@ -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;

View File

@ -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" />

View File

@ -1,4 +1,5 @@
export { export {
onModalNoPage,
onModalFrame, onModalFrame,
onModalPage, onModalPage,
onModalLayout, onModalLayout,

View File

@ -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" />

View 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);
})
}

View File

@ -0,0 +1,4 @@
<StackLayout backgroundColor="lightGreen" loaded="onLoaded">
<Button text="Show Dialog" tap="showDialog"/>
<Button text="Close Modal" tap="closeModal" />
</StackLayout>

View File

@ -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);
})
} }

View File

@ -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" />

View File

@ -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;

View File

@ -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) {

View File

@ -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;