From 3236b3835ec56d256490d68e88a904a6a554bf1d Mon Sep 17 00:00:00 2001 From: "Frank A. Krueger" Date: Fri, 7 Jul 2017 16:58:38 -0700 Subject: [PATCH] Implement Present for iOS --- Ooui/Platform.cs | 122 +++++++++++++++++++++++-- Ooui/UI.cs | 25 +---- PlatformTests/iOSTests/PresentTests.cs | 2 +- PlatformTests/iOSTests/iOSTests.csproj | 3 + 4 files changed, 119 insertions(+), 33 deletions(-) diff --git a/Ooui/Platform.cs b/Ooui/Platform.cs index a784403..e186c6c 100644 --- a/Ooui/Platform.cs +++ b/Ooui/Platform.cs @@ -1,19 +1,123 @@ using System; +using System.Diagnostics; +using System.Linq; +using System.Reflection; namespace Ooui { static class Platform { -#if __IOS32423__ - public static void Present (string url, object presenter) - { + static readonly Assembly iosAssembly; + static readonly Type iosUIViewControllerType; + static readonly Type iosUIApplicationType; + static readonly Type iosUIWebViewType; + static readonly Type iosNSUrl; + static readonly Type iosNSUrlRequest; - } -#else - public static void Present (string url, object presenter) - { + static Platform () + { + var asms = AppDomain.CurrentDomain.GetAssemblies ().ToDictionary ( + x => x.GetName().Name); - } -#endif + asms.TryGetValue ("Xamarin.iOS", out iosAssembly); + if (iosAssembly != null) { + iosUIViewControllerType = iosAssembly.GetType ("UIKit.UIViewController"); + iosUIApplicationType = iosAssembly.GetType ("UIKit.UIApplication"); + iosUIWebViewType = iosAssembly.GetType ("UIKit.UIWebView"); + iosNSUrl = iosAssembly.GetType ("Foundation.NSUrl"); + iosNSUrlRequest = iosAssembly.GetType ("Foundation.NSUrlRequest"); + } + } + + public static void OpenBrowser (string url, object presenter) + { + if (iosAssembly != null) { + OpenBrowserOniOS (url, presenter); + } + else { + StartBrowserProcess (url); + } + } + + static void OpenBrowserOniOS (string url, object presenter) + { + var presenterType = GetObjectType (presenter); + + // + // Find a presenter view controller + // 1. Try the given presenter + // 2. Find the key window vc + // 3. Create a window? + // + object presenterViewController = null; + if (presenter != null && iosUIViewControllerType.IsAssignableFrom (presenterType)) { + presenterViewController = presenter; + } + + if (presenterViewController == null) { + var app = iosUIApplicationType.GetProperty ("SharedApplication").GetValue (null, null); + var window = iosUIApplicationType.GetProperty ("KeyWindow").GetValue (app, null); + if (window != null) { + var rvc = window.GetType ().GetProperty ("RootViewController").GetValue (window, null); + if (rvc != null) { + var pvc = rvc.GetType ().GetProperty ("PresentedViewController").GetValue (rvc, null); + presenterViewController = pvc ?? rvc; + } + } + } + + if (presenterViewController == null) { + throw new InvalidOperationException ("Cannot find a view controller from which to present"); + } + + // + // Create the browser + // + var browserVC = Activator.CreateInstance (iosUIViewControllerType); + var browserV = Activator.CreateInstance (iosUIWebViewType); + + var nsUrl = iosNSUrl.GetMethod ("FromString").Invoke (null, new object[] { url }); + var nsUrlRequest = iosNSUrlRequest.GetMethod ("FromUrl").Invoke (null, new object[] { nsUrl }); + iosUIWebViewType.GetMethod ("LoadRequest").Invoke (browserV, new object[] { nsUrlRequest }); + iosUIViewControllerType.GetProperty ("View").SetValue (browserVC, browserV, null); + + var m = iosUIViewControllerType.GetMethod ("PresentViewController"); + + Console.WriteLine (presenterViewController); + Console.WriteLine (browserVC); + m.Invoke (presenterViewController, new object[] { browserVC, false, null }); + } + + static Type GetObjectType (object o) + { + var t = typeof (object); + if (o is IReflectableType rt) { + t = rt.GetTypeInfo ().AsType (); + } + else if (o != null) { + t = o.GetType (); + } + return t; + } + + static Process StartBrowserProcess (string url) + { + var cmd = url; + var args = ""; + + var osv = Environment.OSVersion; + if (osv.Platform == PlatformID.Unix) { + cmd = "open"; + args = url; + } + + // var vs = Environment.GetEnvironmentVariables (); + // foreach (System.Collections.DictionaryEntry kv in vs) { + // System.Console.WriteLine($"K={kv.Key}, V={kv.Value}"); + // } + + Console.WriteLine ($"Process.Start {cmd} {args}"); + return Process.Start (cmd, args); + } } } diff --git a/Ooui/UI.cs b/Ooui/UI.cs index 613e54a..5f63b86 100644 --- a/Ooui/UI.cs +++ b/Ooui/UI.cs @@ -95,29 +95,8 @@ namespace Ooui var localHost = host == "*" ? "localhost" : host; var url = $"http://{localHost}:{port}{path}"; Console.WriteLine ($"PRESENT {url}"); - - var cmd = url; - var args = ""; - - var osv = Environment.OSVersion; - if (osv.Platform == PlatformID.Unix) { - cmd = "open"; - args = url; - } - - // var vs = Environment.GetEnvironmentVariables (); - // foreach (System.Collections.DictionaryEntry kv in vs) { - // System.Console.WriteLine($"K={kv.Key}, V={kv.Value}"); - // } - - Console.WriteLine ($"EXEC {cmd} {args}"); - try { - System.Diagnostics.Process.Start (cmd, args); - } - catch (Exception ex) { - Error ("FAILED TO EXEC", ex); - } - } + Platform.OpenBrowser (url, presenter); + } static void Start () { diff --git a/PlatformTests/iOSTests/PresentTests.cs b/PlatformTests/iOSTests/PresentTests.cs index 91c7143..04bdeeb 100644 --- a/PlatformTests/iOSTests/PresentTests.cs +++ b/PlatformTests/iOSTests/PresentTests.cs @@ -10,7 +10,7 @@ namespace iOSTests [TestCase] public void Present () { - var b = new Button (); + var b = new Button ("Click Me"); UI.Publish ("/b", b); UI.Present ("/b"); } diff --git a/PlatformTests/iOSTests/iOSTests.csproj b/PlatformTests/iOSTests/iOSTests.csproj index a29b8ad..ea7508f 100644 --- a/PlatformTests/iOSTests/iOSTests.csproj +++ b/PlatformTests/iOSTests/iOSTests.csproj @@ -201,6 +201,9 @@ Tests\UITests.cs + + Ooui\Platform.cs +