Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update IOSWebViewManager.cs #4158

Merged
merged 3 commits into from
Jan 25, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 110 additions & 2 deletions src/BlazorWebView/src/Maui/iOS/IOSWebViewManager.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
using System;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.Encodings.Web;
using Foundation;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.Extensions.FileProviders;
using UIKit;
using WebKit;

namespace Microsoft.AspNetCore.Components.WebView.Maui
{
public class IOSWebViewManager : WebViewManager
Expand Down Expand Up @@ -53,6 +54,113 @@ internal void MessageReceivedInternal(Uri uri, string message)
private void InitializeWebView()
{
_webview.NavigationDelegate = new WebViewNavigationDelegate(_blazorMauiWebViewHandler);
_webview.UIDelegate = new WebViewUIDelegate(_blazorMauiWebViewHandler);
}

internal sealed class WebViewUIDelegate : WKUIDelegate
{
private static readonly string LocalOK = NSBundle.FromIdentifier("com.apple.UIKit").GetLocalizedString("OK");
private static readonly string LocalCancel = NSBundle.FromIdentifier("com.apple.UIKit").GetLocalizedString("Cancel");
private readonly BlazorWebViewHandler _webView;

public WebViewUIDelegate(BlazorWebViewHandler webView)
{
_webView = webView ?? throw new ArgumentNullException(nameof(webView));
}


public override void RunJavaScriptAlertPanel(WKWebView webView, string message, WKFrameInfo frame, Action completionHandler)
{
PresentAlertController(
webView,
message,
okAction: _ => completionHandler()
);
}

public override void RunJavaScriptConfirmPanel(WKWebView webView, string message, WKFrameInfo frame, Action<bool> completionHandler)
{
PresentAlertController(
webView,
message,
okAction: _ => completionHandler(true),
cancelAction: _ => completionHandler(false)
);
}

public override void RunJavaScriptTextInputPanel(
WKWebView webView, string prompt, string? defaultText, WKFrameInfo frame, Action<string> completionHandler)
{
PresentAlertController(
webView,
prompt,
defaultText: defaultText,
okAction: x => completionHandler(x.TextFields[0].Text!),
cancelAction: _ => completionHandler(null!)
);
}

private static string GetJsAlertTitle(WKWebView webView)
{
// Emulate the behavior of UIWebView dialogs.
// The scheme and host are used unless local html content is what the webview is displaying,
// in which case the bundle file name is used.
if (webView.Url != null && webView.Url.AbsoluteString != $"file://{NSBundle.MainBundle.BundlePath}/")
return $"{webView.Url.Scheme}://{webView.Url.Host}";

return new NSString(NSBundle.MainBundle.BundlePath).LastPathComponent;
}

private static UIAlertAction AddOkAction(UIAlertController controller, Action handler)
{
var action = UIAlertAction.Create(LocalOK, UIAlertActionStyle.Default, (_) => handler());
controller.AddAction(action);
controller.PreferredAction = action;
return action;
}

private static UIAlertAction AddCancelAction(UIAlertController controller, Action handler)
{
var action = UIAlertAction.Create(LocalCancel, UIAlertActionStyle.Cancel, (_) => handler());
controller.AddAction(action);
return action;
}

private static void PresentAlertController(
WKWebView webView,
string message,
string? defaultText = null,
Action<UIAlertController>? okAction = null,
Action<UIAlertController>? cancelAction = null)
{
var controller = UIAlertController.Create(GetJsAlertTitle(webView), message, UIAlertControllerStyle.Alert);

if (defaultText != null)
controller.AddTextField((textField) => textField.Text = defaultText);

if (okAction != null)
AddOkAction(controller, () => okAction(controller));

if (cancelAction != null)
AddCancelAction(controller, () => cancelAction(controller));

GetTopViewController(UIApplication.SharedApplication.Windows.FirstOrDefault(m => m.IsKeyWindow)?.RootViewController)?
.PresentViewController(controller, true, null);
}

private static UIViewController? GetTopViewController(UIViewController? viewController)
{
if (viewController is UINavigationController navigationController)
return GetTopViewController(navigationController.VisibleViewController);

if (viewController is UITabBarController tabBarController)
return GetTopViewController(tabBarController.SelectedViewController!);

if (viewController?.PresentedViewController != null)
return GetTopViewController(viewController.PresentedViewController);

return viewController;
}
}

internal class WebViewNavigationDelegate : WKNavigationDelegate
Expand Down