From b1d11d0a93eaa113c992ff843a767a29a2c5a54a Mon Sep 17 00:00:00 2001 From: Carl de Billy Date: Wed, 22 Jul 2020 14:18:25 -0400 Subject: [PATCH] feat(wasm): Added javascript helpers for Wasm, to allow interop with javascript after the new packaging system. --- .../Uno.UI.Lottie/Uno.UI.Lottie.Wasm.csproj | 3 +- .../Xaml/UIElementWasmExtensions.cs | 184 ++++++++++++++++++ src/Uno.UI/AssemblyInfo.cs | 1 + src/Uno.UI/UI/Xaml/UIElement.wasm.cs | 7 +- .../UI/Xaml/UIElementExtensions.wasm.cs | 54 ----- .../UI/Xaml/WindowManagerInterop.wasm.cs | 5 + 6 files changed, 193 insertions(+), 61 deletions(-) create mode 100644 src/Uno.UI.Runtime.WebAssembly/Xaml/UIElementWasmExtensions.cs delete mode 100644 src/Uno.UI/UI/Xaml/UIElementExtensions.wasm.cs diff --git a/src/AddIns/Uno.UI.Lottie/Uno.UI.Lottie.Wasm.csproj b/src/AddIns/Uno.UI.Lottie/Uno.UI.Lottie.Wasm.csproj index f4d741bca252..40f9de2ddd21 100644 --- a/src/AddIns/Uno.UI.Lottie/Uno.UI.Lottie.Wasm.csproj +++ b/src/AddIns/Uno.UI.Lottie/Uno.UI.Lottie.Wasm.csproj @@ -32,7 +32,8 @@ - + + diff --git a/src/Uno.UI.Runtime.WebAssembly/Xaml/UIElementWasmExtensions.cs b/src/Uno.UI.Runtime.WebAssembly/Xaml/UIElementWasmExtensions.cs new file mode 100644 index 000000000000..70a38630f981 --- /dev/null +++ b/src/Uno.UI.Runtime.WebAssembly/Xaml/UIElementWasmExtensions.cs @@ -0,0 +1,184 @@ +using System; +using Windows.UI.Xaml; +using Uno.UI.Xaml; +using System.Threading.Tasks; +using Uno.Extensions; +using Uno.Foundation; + +namespace Windows.UI.Xaml +{ + public static class UIElementWasmExtensions + { + /// + /// Get the Id of the corresponding element in the HTML DOM + /// + public static string GetHtmlId(this UIElement element) + { + return element.HtmlId.ToString(); + } + + /// + /// Set one or many CSS styles on a HTML element. + /// + /// + /// The style is using the CSS syntax format, not the DOM syntax. + /// Ex: for font size, use "font-size", not "fontSize". + /// + public static void SetCssStyle(this UIElement element, params (string name, string value)[] styles) + { + WindowManagerInterop.SetStyles(element.HtmlId, styles); + } + + /// + /// Clear one or may CSS styles from a HTML element. + /// + public static void ResetCssStyle(this UIElement element, params string[] names) + { + WindowManagerInterop.ResetStyle(element.HtmlId, names); + } + + /// + /// Set one of the predefined class + /// + /// + /// Useful to switch a control from different modes when each mode is bound + /// to a specific class. + /// + public static void SetCssClass(this UIElement element, string[] classes, int index) + { + WindowManagerInterop.SetClasses(element.HtmlId, classes, index); + } + + /// + /// Add one or many CSS classes to a HTML element, if not present. + /// + public static void SetCssClasses(this UIElement element, params string[] classesToSet) + { + WindowManagerInterop.SetUnsetCssClasses(element.HtmlId, classesToSet, null); + } + + /// + /// Remove one or many CSS classes from a HTML element, if defined. + /// + public static void UnsetCssClasses(this UIElement element, params string[] classesToUnset) + { + WindowManagerInterop.SetUnsetCssClasses(element.HtmlId, null, classesToUnset); + } + + /// + /// Set a HTML attribute to an element. + /// + public static void SetHtmlAttribute(this UIElement element, string name, string value) + { + WindowManagerInterop.SetAttribute(element.HtmlId, name, value); + } + + /// + /// Set multiple HTML attributes to an element at the same time. + /// + public static void SetHtmlAttributes(this UIElement element, params (string name, string value)[] attributes) + { + WindowManagerInterop.SetAttributes(element.HtmlId, attributes); + } + + /// + /// Clear/remove a HTML attribute from an element. + /// + public static void RemoteHtmlAttribute(this UIElement element, string name) + { + WindowManagerInterop.RemoveAttribute(element.HtmlId, name); + } + + /// + /// Run javascript in the context of a DOM element. + /// This one is available in the scope as "element". + /// + /// + /// Will work even if the element is not yet loaded into the DOM. + /// + public static string ExecuteJavascript(this UIElement element, string jsCode) + { + var js = @$" +(function(element) {{ +{jsCode} +}})(Uno.UI.WindowManager.current.getView({element.HtmlId})); +"; + return WebAssemblyRuntime.InvokeJS(js); + } + + /// + /// Asynchronously run javascript on a DOM element. + /// This one is available in the scope as "element". + /// The called code is expected to return something awaitable (a Promise). + /// + /// + /// Will work even if the element is not yet loaded into the DOM. + /// + public static Task ExecuteJavascriptAsync(this UIElement element, string asyncJsCode) + { + var js = @$" +(function(element) {{ +const __f = () => {asyncJsCode}; +return __f(element); +}})(Uno.UI.WindowManager.current.getView({element.HtmlId})); +"; + return WebAssemblyRuntime.InvokeAsync(js); + } + + /// + /// Set raw HTML Content for this element. + /// Don't use this when there's child elements managed by Uno or you'll + /// get expected results. + /// + public static void SetHtmlContent(this UIElement element, string html) + { + WindowManagerInterop.SetContentHtml(element.HtmlId, html); + } + + /// + /// Will invoke `addEventListener()` on the corresponding HTML element. + /// + public static void RegisterHtmlEventHandler(this UIElement element, string eventName, EventHandler handler) + { + element.RegisterEventHandler(eventName, handler); + } + + /// + /// Unregister previously registered event with RegisterHtmlEventHandler. + /// + public static void UnregisterHtmlEventHandler(this UIElement element, string eventName, EventHandler handler) + { + element.UnregisterEventHandler(eventName, handler); + } + + /// + /// Will invoke `addEventListener()` on the corresponding HTML element. + /// + /// + /// For use with CustomEvent("name", {detail:{detail here}}). + /// + /// + /// True will JSON.stringify the content. False will treat the content as a string. + /// + public static void RegisterHtmlCustomEventHandler(this UIElement element, string eventName, EventHandler handler, bool isDetailJson = false) + { + var extractor = isDetailJson + ? UIElement.HtmlEventExtractor.CustomEventDetailJsonExtractor + : UIElement.HtmlEventExtractor.CustomEventDetailStringExtractor; + + element.RegisterEventHandler( + eventName, + handler, + eventExtractor: extractor, + payloadConverter: (_, s) => new HtmlCustomEventArgs(s)); + } + + /// + /// Unregister previously registered event with RegisterHtmlCustomEventHandler. + /// + public static void UnregisterHtmlCustomEventHandler(this UIElement element, string eventName, EventHandler handler) + { + element.UnregisterEventHandler(eventName, handler); + } + } +} diff --git a/src/Uno.UI/AssemblyInfo.cs b/src/Uno.UI/AssemblyInfo.cs index ffd5fd6e446b..0043e4cea5d7 100644 --- a/src/Uno.UI/AssemblyInfo.cs +++ b/src/Uno.UI/AssemblyInfo.cs @@ -5,6 +5,7 @@ [assembly: InternalsVisibleTo("Uno.UI.Tests.Performance")] [assembly: InternalsVisibleTo("Uno.UI.Toolkit")] [assembly: InternalsVisibleTo("Uno.UI.RemoteControl")] +[assembly: InternalsVisibleTo("Uno.UI.Runtime.Wasm")] [assembly: InternalsVisibleTo("Uno.UI.RuntimeTests")] [assembly: InternalsVisibleTo("Uno.UI.RuntimeTests.Wasm")] [assembly: InternalsVisibleTo("Uno.UI.RuntimeTests.Skia")] diff --git a/src/Uno.UI/UI/Xaml/UIElement.wasm.cs b/src/Uno.UI/UI/Xaml/UIElement.wasm.cs index 26dcb6c7a6a8..670faafd1531 100644 --- a/src/Uno.UI/UI/Xaml/UIElement.wasm.cs +++ b/src/Uno.UI/UI/Xaml/UIElement.wasm.cs @@ -119,7 +119,7 @@ public UIElement(string htmlTag, bool isSvg) private static Dictionary _htmlTagCache = new Dictionary(FastTypeComparer.Default); private static Type _htmlElementAttribute; private static PropertyInfo _htmlTagAttributeTagGetter; - private static Assembly _unoUIAssembly = typeof(UIElement).Assembly; + private static readonly Assembly _unoUIAssembly = typeof(UIElement).Assembly; private string GetHtmlTag(string htmlTag) { @@ -278,11 +278,6 @@ protected internal void SetNativeTransform(Matrix3x2 matrix) protected internal void ResetStyle(params string[] names) { - if (names == null || names.Length == 0) - { - // nothing to do - } - Uno.UI.Xaml.WindowManagerInterop.ResetStyle(HtmlId, names); } diff --git a/src/Uno.UI/UI/Xaml/UIElementExtensions.wasm.cs b/src/Uno.UI/UI/Xaml/UIElementExtensions.wasm.cs deleted file mode 100644 index c5f0a0b97829..000000000000 --- a/src/Uno.UI/UI/Xaml/UIElementExtensions.wasm.cs +++ /dev/null @@ -1,54 +0,0 @@ -using System; -using Windows.UI.Xaml; - -namespace Uno.Extensions -{ - public static class UIElementExtensions - { - /// - /// Will invoke `addEventListener()` on the corresponding HTML element. - /// - public static void RegisterHtmlEventHandler(this UIElement element, string eventName, EventHandler handler) - { - element.RegisterEventHandler(eventName, handler); - } - - /// - /// Unregister previously registered event with RegisterHtmlEventHandler. - /// - public static void UnregisterHtmlEventHandler(this UIElement element, string eventName, EventHandler handler) - { - element.UnregisterEventHandler(eventName, handler); - } - - /// - /// Will invoke `addEventListener()` on the corresponding HTML element. - /// - /// - /// For use with CustomEvent("name", {detail:{detail here}}). - /// - /// - /// True will JSON.stringify the content. False will treat the content as a string. - /// - public static void RegisterHtmlCustomEventHandler(this UIElement element, string eventName, EventHandler handler, bool isDetailJson = false) - { - var extractor = isDetailJson - ? UIElement.HtmlEventExtractor.CustomEventDetailJsonExtractor - : UIElement.HtmlEventExtractor.CustomEventDetailStringExtractor; - - element.RegisterEventHandler( - eventName, - handler, - eventExtractor: extractor, - payloadConverter: (_, s) => new HtmlCustomEventArgs(s)); - } - - /// - /// Unregister previously registered event with RegisterHtmlCustomEventHandler. - /// - public static void UnregisterHtmlCustomEventHandler(this UIElement element, string eventName, EventHandler handler) - { - element.UnregisterEventHandler(eventName, handler); - } - } -} diff --git a/src/Uno.UI/UI/Xaml/WindowManagerInterop.wasm.cs b/src/Uno.UI/UI/Xaml/WindowManagerInterop.wasm.cs index 81b2450d1977..a79513bfb940 100644 --- a/src/Uno.UI/UI/Xaml/WindowManagerInterop.wasm.cs +++ b/src/Uno.UI/UI/Xaml/WindowManagerInterop.wasm.cs @@ -861,6 +861,11 @@ private struct WindowManagerDestroyViewParams #region ResetStyle internal static void ResetStyle(IntPtr htmlId, string[] names) { + if (names == null || names.Length == 0) + { + // nothing to do + } + if (UseJavascriptEval) { if (names.Length == 1)